Closed lbialy closed 5 months ago
Sounds good. For the record, you are right, Java uses CompletableFuture.allOf like this
public static <T> CompletableFuture<List<T>> allOf(Collection<CompletableFuture<T>> futures) {
return CompletableFuture
.allOf(futures.toArray(new CompletableFuture[futures.size()]))
.thenApply(unused -> futures.stream()
.filter(ignoreNullValues())
.map(CompletableFuture::join) // join() is not blocking here, by the time this function is called, the future is guaranteed to be complete
.collect(Collectors.toList())
);
}
This will wait for all of the futures without any ordering. So it can be parallel in theory.
In java it is parallel by default because CompletableFuture is not lazy :)
Implemented and done.
I remember there was some nuance regarding supply
vs. supplyAsync
but I don't remember the details any more ;)
Current implementation of sequence/traverse functions is sequential which can very easily lead to accidental serialisation of operations. Given that resource constructors can be painfully slow in infra it should be possible for the user to decide whether their side effects have to be executed in given order or in parallel. We could just make
sequence
andtraverse
parallel by default (I think that's howOutput.allOf
works inpulumi-java
andAll
/Output.all
combinators in other SDKs work given that all of them are strict!) but that could be misleading, surprising and not really helpful for people used to working with lazy monads in Scala.