Skip to content

Commit

Permalink
OKAPI-943: GenericCompositeFuture
Browse files Browse the repository at this point in the history
Coordinate a List<Future<T extends Future <?>>>, provides
all(List<T>), any(List<T>) and join(List<T>) that work like
CompositeFuture#all(List), CompositeFuture#any(List) and
CompositeFuture#join(List) but properly check the
generic type <T extends Future<?>>.

See eclipse-vertx/vert.x#3595 why Vert.x doesn't have this.
  • Loading branch information
julianladisch committed Nov 4, 2020
1 parent 1d0ed9e commit b16af62
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 0 deletions.
5 changes: 5 additions & 0 deletions okapi-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
<artifactId>vertx-unit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.folio.okapi.common;

import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import io.vertx.core.impl.future.CompositeFutureImpl;
import java.util.List;

/**
* Coordinate a {@code List<Future<T extends Future <?>>>}, provides
* {@link #all(List) all(List&lt;T>)}, {@link #any(List) any(List&lt;T>)} and
* {@link #join(List) join(List&lt;T>)} that work like
* {@link CompositeFuture#all(List)}, {@link CompositeFuture#any(List)} and
* {@link CompositeFuture#join(List)} but properly check the generic type
* {@code <T extends Future<?>>}.
* <p>
* See <a href="https://github.com/eclipse-vertx/vert.x/pull/3595">
* https://github.com/eclipse-vertx/vert.x/pull/3595</a>
* why Vert.x doesn't have this.
*/
public interface GenericCompositeFuture {
/**
* Return a composite future, succeeded when all futures are succeeded,
* failed as soon as one of the futures is failed.
* <p/>
* When the list is empty, the returned future will be already succeeded.
* <p/>
* This is the same as {@link CompositeFuture#all(List)} but with generic type declaration.
*/
static <T extends Future<?>> CompositeFuture all(List<T> futures) {
return CompositeFutureImpl.all(futures.toArray(new Future[futures.size()]));
}

/**
* Return a composite future, succeeded as soon as one future is succeeded,
* failed when all futures are failed.
* <p/>
* When the list is empty, the returned future will be already succeeded.
* <p/>
* This is the same as {@link CompositeFuture#any(List)} but with generic type declaration.
*/
static <T extends Future<?>> CompositeFuture any(List<T> futures) {
return CompositeFutureImpl.any(futures.toArray(new Future[futures.size()]));
}

/**
* Return a composite future, succeeded when all {@code futures} are succeeded,
* failed when any of the {@code futures} is failed.
* <p/>
* It always waits until all its {@code futures} are completed and will not fail
* as soon as one of the {@code futures} fails.
* <p/>
* When the list is empty, the returned future will be already succeeded.
* <p/>
* This is the same as {@link CompositeFuture#join(List)} but with generic type declaration.
*/
static <T extends Future<?>> CompositeFuture join(List<T> futures) {
return CompositeFutureImpl.join(futures.toArray(new Future[futures.size()]));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package org.folio.okapi.common;

import io.vertx.core.AsyncResult;
import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import org.assertj.core.api.WithAssertions;
import org.junit.Test;

public class GenericCompositeFutureTest implements WithAssertions {
@Test
public void success() {
List<Future<String>> successSuccess = Arrays.asList(Future.succeededFuture(), Future.succeededFuture());
List<Future<String>> successFailure = Arrays.asList(Future.succeededFuture(), Future.failedFuture(""));
assertThat(GenericCompositeFuture.all(successSuccess).succeeded()).isTrue();
assertThat(GenericCompositeFuture.all(successFailure).failed()).isTrue();
assertThat(GenericCompositeFuture.any(successSuccess).succeeded()).isTrue();
assertThat(GenericCompositeFuture.any(successFailure).succeeded()).isTrue();
assertThat(GenericCompositeFuture.join(successSuccess).succeeded()).isTrue();
assertThat(GenericCompositeFuture.join(successFailure).failed()).isTrue();
}

@Test
public void completion() {
List<Future<Integer>> failureAndUnknown = Arrays.asList(Future.failedFuture(""), Promise.<Integer>promise().future());
assertThat(GenericCompositeFuture.all(failureAndUnknown).isComplete()).isTrue();
assertThat(GenericCompositeFuture.any(failureAndUnknown).isComplete()).isFalse();
assertThat(GenericCompositeFuture.join(failureAndUnknown).isComplete()).isFalse();
}

@Test
public void generics() {
List<MyFuture<Double>> list = Collections.emptyList();
CompositeFuture all = GenericCompositeFuture.all(list);
CompositeFuture any = GenericCompositeFuture.any(list);
CompositeFuture join = GenericCompositeFuture.join(list);
assertThat(all.succeeded()).isTrue();
assertThat(any.succeeded()).isTrue();
assertThat(join.succeeded()).isTrue();
}

class MyFuture<T> implements Future<T> {
@Override
public boolean isComplete() {
return false;
}

@Override
public Future<T> onComplete(Handler<AsyncResult<T>> handler) {
return null;
}

@Override
public T result() {
return null;
}

@Override
public Throwable cause() {
return null;
}

@Override
public boolean succeeded() {
return false;
}

@Override
public boolean failed() {
return false;
}

@Override
public <U> Future<U> compose(Function<T, Future<U>> successMapper, Function<Throwable, Future<U>> failureMapper) {
return null;
}

@Override
public <U> Future<U> map(Function<T, U> mapper) {
return null;
}

@Override
public <V> Future<V> map(V value) {
return null;
}

@Override
public Future<T> otherwise(Function<Throwable, T> mapper) {
return null;
}

@Override
public Future<T> otherwise(T value) {
return null;
}
};
}

0 comments on commit b16af62

Please sign in to comment.