Reputation: 13
I'm looking for how in Java given let's say a list of Async CompletableFutures for any of the first N to complete successfully or fail. Any failures ignored unless there are not N successful.
Any examples of this?
Thanks
Upvotes: 1
Views: 335
Reputation: 298243
Perhaps, something like this?
public static <T> CompletableFuture<List<T>> firstSuccessful(
List<CompletableFuture<T>> list, int n) {
int maxFail = list.size() - n;
if(maxFail < 0) throw new IllegalArgumentException();
AtomicInteger fails = new AtomicInteger(0);
List<T> rList = new ArrayList<>(n);
CompletableFuture<List<T>> result = new CompletableFuture<>();
BiConsumer<T,Throwable> c = (value,failure) -> {
if(failure != null) {
if(fails.incrementAndGet() > maxFail) result.completeExceptionally(failure);
}
else {
if(!result.isDone()) {
boolean commit;
synchronized(rList) {
commit = rList.size() < n && rList.add(value) && rList.size() == n;
}
if(commit) result.complete(Collections.unmodifiableList(rList));
}
}
};
for(CompletableFuture<T> f: list) f.whenComplete(c);
return result;
}
It returns the N results as a List
, though the order is undetermined. It’s just that returning a Set
would change the semantic, i.e. when multiple futures evaluated to equal results.
The list will always have the length N, if there were enough successful completions. It will also be completed just when the Nth result is available, not wait for other futures. As soon as there are so many failed futures that a successful completion of N values is not possible anymore, the resulting future will be completed exceptionally. Effectively, it will be an arbitrary throwable out of the failed futures.
Upvotes: 1