public static <T> CompletableFuture<List<T>> waitForAll(
List<CompletableFuture<T>> rawFutures,
int timeout,
ScheduledExecutorService scheduler) {
scheduler.schedule(() -> {
for (CompletableFuture<T> rawFuture : rawFutures) {
if (!rawFuture.isDone()) {
rawFuture.complete(null);
}
}
}, timeout, MILLISECONDS);
return CompletableFuture.allOf(rawFutures.toArray(new CompletableFuture[rawFutures.size()]))
.thenApply(_void -> rawFutures.stream().map(f -> f.getNow(null)).collect(Collectors.toList()));