HI! I am fairly fresh to Kotlin and new to corouti...
# coroutines
k
HI! I am fairly fresh to Kotlin and new to coroutines and flow. I am coming from Java backend so am familiar with threads and completable futures. I am wondering about one scenario, thought I ask here before doing dozens of tests myself: Given external Java API that returns
CompletableFuture
of different entities, for example:
Copy code
getFoo: CompletableFuture<List<FooDto>> 
getBar: CompletableFuture<List<BarDto>>
getWhatever: CompletableFuture<List<WhateverDto>>
Would it be possible to use coroutines to trigger each of the call in parallel, and combine final object to be:
Copy code
Object {
    foo: List<FooDto>
    bar: List<BarDto>
    whatever: List<WhateverDto>
}
It is not so easy and obvious to solve with `CompletableFuture`s in Java, maybe it would be easier with
coroutines
? 🤔 The point is I need to fetch multiple different entities before can calculate the final object. I can easily fetch them in sequence, but they are not dependant on each other, so should really be fetched in parallel
r
Would it be possible to use coroutines to trigger each of the call in parallel, and combine final object to be:
yes You can use
async
await
in co-routines (similar to
get
) and in the end you can combine the results.
k
Just to clarify, I could do
Copy code
getFoo().get()
getBar().get()
getWhatever.get()
In Java, but this is blocking call. Solution you mention means that all calls will be triggered and the process will wait for each of them to finish, meaning will take as long as the longest running task?
u
Something along these lines (untested). Sure this only works inside a suspend function, as
await
is a suspend function
Copy code
val fooFuture = getFoo()
val barFuture = getBar()
val whateverFuture = getWhatever()
Object {
  foo = fooFuture.await()
  bar = barFuture.await()
  whatever = whateverFuture.await()
}
r
k
@raulraja but isn't awaitAll expecting all futures to return the same entity type? (My thought when looking at its signature)
r
awaitAll
on it’s own does not support multiple typed arguments and if your futures or deferred values are of different type. This is why we have
parZip
otherwise
awaitAll
would have worked. In general Kotlin does not let you abstract over arg arity, but in this operation there are multiple concerns such as cancellation and others that otherwise you need to handle manually
@Kamila this why we have to cast in the link inside the impl of parZip but those are safe yet ugly, If it were me I’d probably encapsulate the pattern for the number of operations you want to use and if you want them to be all cancelled automatically on errors and initiated inside the same structured scope
I think it may look similar to this if the services in Java produces futures.
d
I belive you can just use Any for purposes of awaitAll(), if you have the original future still referenced you can get the return value from that after await/awaitAll returns -- just ignore non-error returns and go back to the original futures and call get() again -- avoiding having to create type specific code just to make awaitAll happy.