-
Notifications
You must be signed in to change notification settings - Fork 362
fix: respect custom coroutine scope when calling blocking functions in a data fetcher #2116
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
base: master
Are you sure you want to change the base?
fix: respect custom coroutine scope when calling blocking functions in a data fetcher #2116
Conversation
1387547
to
492f993
Compare
👍🏻 |
Could you add test case for it? |
Sure! |
…n a data fetcher When running blocking function data fetcher it does not respect coroutine scope provided in the GraphQL context. In my project we're creating custom a coroutine scope in order to propagate MDC and OTEL contexts in a coroutine like this: ``` CoroutineScope(MDCContext() + Dispatchers.IO + Context.current().asContextElement()) ``` (here `Context` is an instance of OTEL context). This works well in suspended functions since they are using the context however normal functions are not using this context and therefore none of the OTEL context (trace id etc) is propagated.
492f993
to
48a2b88
Compare
Added tests @Samjin |
parameterValues: Map<KParameter, Any?> | ||
): Any? = try { | ||
val coroutineScope = environment.graphQlContext.getOrDefault(CoroutineScope(EmptyCoroutineContext)) | ||
runBlocking(coroutineScope.coroutineContext) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do understand the reasoning behind this change, but think about it, running a blocking function in a coroutine could be catastrophic just because you need context propagation, there should be another way to deal with this issue.
I do not know your use case, but this issue requires a different solution, and for now, what I would advice is to mark the resolver/function as suspend, what is blocking inside your resolver ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not know your use case, but this issue requires a different solution, and for now, what I would advice is to mark the resolver/function as suspend, what is blocking inside your resolver ?
Dataloaders don't play nice with suspended functions. Because of that all functions which resolve properties via dataloaders are not suspended and the trace breaks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the concern of running blocking code in a coroutine but it's not dramatically worse than running it in an arbitrary thread, is it?
What if we supply another coroutine scope specifically for sync functions to avoid blocks on suspended functions?
📝 Description
When running blocking function data fetcher it does not respect coroutine scope provided in the GraphQL context.
In my project we're creating custom a coroutine scope in order to propagate MDC and OTEL contexts in a coroutine like this:
(here
Context
is an instance of OTEL context).This works well in suspended functions since they are using the context however normal functions are not using this context and therefore none of the OTEL context (trace id etc) is propagated.
🔗 Related Issues