Jaro
03/24/2023, 3:54 PMCompletableFuture
code in Java to Coroutines
in Kotlin, the interface that my Kotlin class implements has functions that are returning CompletableFuture
Here is example of functions that I want to rewrite
private final Map<String, FooWrapper> fooRequests = new ConcurrentHashMap<>();
public CompletableFuture<FooResponse> retrieveFoo(FooRequest request) {
return completedFuture(...)
.thenAccept(client::callFoo)
.thenCompose(ignore -> storeFooRequest(request))
.whenComplete((response, error) -> log(request, error));
}
private CompletableFuture<FooResponse> storeFooRequest(FooRequest request) {
var fooWrapper = new FooWrapper(request, new CompletableFuture<>());
fooRequests.put(request.getId(), fooWrapper);
return fooWrapper.getResponseFuture();
}
eventually there will be call to other functions that will call complete
on a CompletableFuture
stored in fooRequests
and allowing completion of retrieveFoo
here is my Kotlin code
private val fooRequests: ConcurrentHashMap<String, CompletableDeferred<FooResponse>> = ConcurrentHashMap()
override fun retrieveFoo(request: FooRequest): CompletableFuture<FooResponse> {
return GlobalScope.future {
retrieveQuoteAsync(request)
}
}
private suspend fun retrieveFooAsync(request: FooRequest): Deferred<FooResponse> {
return coroutineScope {
storeFooRequest(request)//.await()
}
}
private suspend fun storeFooRequest(request: FooRequest): Deferred<FooResponse> {
val deferred: CompletableDeferred<FooResponse> = CompletableDeferred()
fooRequests[request.id] = deferred
return deferred
}
I'm trying to replace CompletableFuture
with CompletableDeferred
but I do not know how to get the value without calling await()
, I do not want it to block
Any suggestion how to make it work in similar way to Java?Joffrey
03/24/2023, 3:57 PMCompletableFuture
? If that's not the case, you should prefer turning your functions into suspend functions instead, and get rid of the futures in return types, it would simplify everything.Jaro
03/24/2023, 4:00 PMJoffrey
03/24/2023, 4:00 PMbut I do not know how to get the value without calling await() , I do not want it to blockCalling
await()
doesn't block. It suspends the current coroutine, which is non-blocking (that's the whole point)Jaro
03/24/2023, 4:01 PMawait()
?Joffrey
03/24/2023, 4:02 PMfuture { ... }
coroutine builder already, you can simply await. It will suspend the coroutine created by the future
builder without blocking any thread.Joffrey
03/24/2023, 4:05 PMGlobalScope
. Use either an existing scope, or create a new scope that is tied to the lifecycle of the component that holds all concurrent coroutines. It probably has a close()
or shutdown()
method to stop all concurrent work, and you should use it to cancel all pending requests by cancelling the coroutine scope in which you launched all the coroutinesJaro
03/24/2023, 4:12 PMcancel()
on the coroutineScope
?Joffrey
03/24/2023, 4:21 PMretrieveFoo
as cancelled (isCancelled == true
), and calling .get()
on them will throw JobCancellationException
.Jaro
03/24/2023, 4:31 PM