Skip to content

Clarify impact on the reactive execution model when using kotlin coroutines #44930

Open
@mschirmacher

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

  1. 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

  2. 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 :-)

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions