Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request - default CoroutineContext #36875

Open
pkozakCC opened this issue Nov 5, 2023 Discussed in #36738 · 8 comments
Open

Feature Request - default CoroutineContext #36875

pkozakCC opened this issue Nov 5, 2023 Discussed in #36738 · 8 comments
Labels
area/kotlin triage/needs-feedback We are waiting for feedback.

Comments

@pkozakCC
Copy link

pkozakCC commented Nov 5, 2023

Discussed in #36738

Originally posted by pkozakCC October 27, 2023
There are cases where the default CoroutineContext has to be modified for all suspendable RestEasy Resource method calls, for example in order to add a custom CoroutineContext.Element for every request, that would hold application-specific details, such as tenant ID (which is precisely my case btw).

This can be done manually, but it's tedious and error-prone.

It would be nice to introduce a mechanism that would make it possible to modify the default CoroutineContext.
It can be either of a form CoroutineWebFilter, that would return a suspendable function and would respect the context in the downstream, e.g.:

    suspend fun filter(
        serverWebExchange: ServerWebExchange,
        webFilterChain: CoroutineWebFilterChain,
    ): Mono<Void> {
        return withContext(MyCustomCoroutineContextElement()) {
            webFilterChain.filter(serverWebExchange)
        }
    }

    interface CoroutineWebFilterChain {
        suspend fun filter(serverWebExchange: ServerWebExchange): Mono<Void>
    }

Or similarly to the Spring approach (links below) - registering a list of CoroutineContext.Element in a filter (per request)

After:

Spring Webflux approach for the issue (which will be released in 6.1) - current implementation of CoWebFilter does not respect the CoroutineContext changes:

@quarkus-bot
Copy link

quarkus-bot bot commented Nov 5, 2023

/cc @evanchooly (kotlin), @geoand (kotlin)

@geoand
Copy link
Contributor

geoand commented Nov 6, 2023

Do you have some example of what exactly you are trying to do?
I am asking because I would like to get a sense of what problem we are trying to solve here.

Thanks

@geoand geoand added the triage/needs-feedback We are waiting for feedback. label Nov 6, 2023
@mschorsch
Copy link
Contributor

mschorsch commented Nov 8, 2023

The author would like to have a possibility to modify the CoroutineContext before calling the resteasy reactive endpoint, with the aim of storing additional data in the CoroutineContext. This data would then be automatically available via the CoroutineContext in all suspendable resteasy reactive endpoints. The advantage of the CoroutineContext is that it is automatically propagated by the Kotlin coroutines and therefore no longer needs to be managed by the user. A typical use case is the use of the MDC (https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-slf4j/kotlinx.coroutines.slf4j/-m-d-c-context/). In this case, the author probably wants to pass the tenantId for all resteasy reactive resources.

+1

@geoand
Copy link
Contributor

geoand commented Nov 8, 2023

The author would like to have a possibility to modify the CoroutineContext before calling the resteasy reactive endpoint, with the aim of storing additional data in the CoroutineContex

Yeah, I get that. What I want to see is some pseudo-example of what this would be used for

@cogman
Copy link

cogman commented Nov 27, 2023

@geoand here's what I'd like to do.

@GET
suspend fun getIt(id: Int): It {
  MDC.put("get.id", id)
  return withContext(Dispatcher.IO) {
    dao.getIt(id)
  }
}

With a default coroutine context (or something like it). I could set it up as

  fun defaultSetup(rootContext: Context): Context {
    return rootContext.plus(MDCContext())
  }

This would propagate MDC values through coroutine calls (which is what I want to do).

In order to do this as of now, I have to do something like this on every endpoint

  fun getIt(id: Int): It = withContext(MDCContext()) {
    return@withContext etc()
  }

@geoand
Copy link
Contributor

geoand commented Dec 1, 2023

Thanks for the update!

@geoand
Copy link
Contributor

geoand commented Dec 7, 2023

@cogman I think I have an idea of how to make this work, but what would be super helpful in testing it would be if you could attach a sample application where you are using the feature you mention above.

Thanks

@geoand
Copy link
Contributor

geoand commented Jun 7, 2024

@cogman ^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/kotlin triage/needs-feedback We are waiting for feedback.
Projects
None yet
Development

No branches or pull requests

4 participants