-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Request context is not preserved across Kotlin coroutines #45441
Comments
/cc @geoand (kotlin) |
Can you please provide a sample application that shows the problem you mention? Thanks |
I made a code snippet to demonstrate it. If you want a full demo application let me know. This is an example of a case where it is broken and does not work: class CoroutineRequestContextReproducer {
@RequestScoped
class C {
// Must be called from a function that has a request context due to the @RequestScoped annotation
suspend fun sleep() {
delay(1000)
}
}
@Inject
private lateinit var c: C
@ActivateRequestContext
fun a() = runBlocking {
// This will work
c.sleep()
// This will not work
async {
// The request context is now lost, as it is not propagated to the coroutine
b()
}
}
suspend fun b() {
c.sleep()
}
} This case will however work when using a coroutine : class CoroutineRequestContextReproducer {
@RequestScoped
class C {
// Must be called from a function that has a request context due to the @RequestScoped annotation
suspend fun sleep() {
delay(1000)
}
}
@Inject
private lateinit var c: C
fun a() = runBlocking {
// This will not work, because a is not annotated with @ActivateRequestContext
c.sleep()
// The context would have been lost here, but we declare the context within the coroutine
async {
b()
}
}
@ActivateRequestContext
suspend fun b() {
/// This will now work, because b is annotated with @ActivateRequestContext and is already within the coroutine
c.sleep()
}
} |
That would be helpful, thanks! |
@geoand here's a simple Quarkus command app that reproduces the issue: |
That's a great reproducer, thanks! The problem is indeed clear (the request scope is not propagated to the coroutine thread), but as I've not looked deep at coroutines in a while, I am unsure how it's supposed to be solved. |
Thanks for looking into it! |
You can use something similar to what we do in Quarkus REST to support coroutines. In there you'll see we capture the CDI scope and the context classloader in order to make everything work as expected. |
Describe the bug
I was working with an
@RequestScoped
bean and@ActivateRequestContext
, however, I kept running into errors with the request scope not being active when calling my bean, even though I used@ActivateRequestContext
. It turns out this happens because the request context is lost when passing to a Kotlin coroutine.I am unsure as to whether you would want this to be supported given the thread-safe nature of RequestScoped. However, micronaut seems to have run into a similar issue and then fixed it (micronaut-projects/micronaut-core#4661). If this behaviour should not be changed, it would be nice to at least have this in the documentation as this took a lot of time to realise/figure out.
Expected behavior
No response
Actual behavior
No response
How to Reproduce?
No response
Output of
uname -a
orver
No response
Output of
java -version
No response
Quarkus version or git rev
No response
Build tool (ie. output of
mvnw --version
orgradlew --version
)No response
Additional information
No response
The text was updated successfully, but these errors were encountered: