Clarify impact on the reactive execution model when using kotlin coroutines #44930
Description
Description
Context and background
As a starting point please have a look into this innocent piece of code:
https://github.com/mschirmacher/QuarkusAuthorizationPolicySuspendBug/blob/e07c0a88e1417ab155ca0cb288569eb3791e0a92/src/main/kotlin/org/acme/GreetingResource.kt
We see here a non-suspending rest endpoint that returns an Uni
. To create the Uni
im call the uni
builder function of the flavor, that allows calling a kotlin suspend method inside.
What it calls is method of the FooService#doSomething
, that indeed is a suspend
method and it tries to access the CurrentIdentityAssociation
to evaluate permissions of the user.
So far so good so easy.
The only problem is: it doesn't work!
The reason for that is, as Michal Vavrik pointed out in this thread is, inside the FooService, there is a second, empty CDI context, which is different to the request context.
And together with Georgios Andrianakis i could fix it, by using a VertxDisaptcher for the coroutine. like so: mschirmacher/QuarkusAuthorizationPolicySuspendBug@7b91935
proposal for improvement
At least these 2 guides
- https://quarkus.io/guides/kotlin
- https://quarkus.io/guides/quarkus-reactive-architecture
Should contain information about how using kotlin coroutines play together with the reactive architecture. A few questions that should be answered from my point of view: - on what threads will the coroutine run?
- what is the default when declaring suspending rest endpoints
- how and why using the wrong thread will lead to bugs/problems in the code?
- which of the official kotlinx.coroutines Dispatcher can or should not be used?
- The crucial difference between the terms "I/O" as used in the reactive architecture guide and Dispatchers.IO1
nice to have
Maybe it is even possible to go step further and provide an easy way to access the correct (Coroutine)Dispatcher when it is needed.
Similar to what kotlinx.coroutines library does, it might be possible to provide a singleton with some constants like:
- ReactiveDispatchers.NON_BLOCKING_IO to access the vertx i/o threads
- ReactiveDispatchers.BLOCKING_IO to do blocking i/o similar to kotlinx Dispatchers.IO
- ReactiveDispatchers.WORKER for long running tasks2
And as an addition Dispatchers.Main maybe could be wired to point to the Vertx main thread.
What do you think?
Implementation ideas
No response
Footnotes
-
in the reactive architecture, if i understand correctly, it is crucial, that only NON-blocking i/o is used on an i/o thread, while in the kotlin world, there is a large pool of threads backing the IO dispatcher meant to be used for BLOCKING i/o ↩
-
probably bad naming, because, if i understand correctly, a worker from the reactive architecture point of view can also do blocking i/o. but you get my point, i hope :-) ↩