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

ktor-server: What coroutine context should be used? #2016

Open
fpetwo opened this issue Jul 13, 2024 · 2 comments
Open

ktor-server: What coroutine context should be used? #2016

fpetwo opened this issue Jul 13, 2024 · 2 comments

Comments

@fpetwo
Copy link

fpetwo commented Jul 13, 2024

I have the resolver shown below. It can access its current CoroutineContext object but also another CoroutineContext object via the DataFetchingEnvironment.

class MyResolver : Query {
    suspend fun myQuery(dfe: DataFetchingEnvironment): String {
        val currentCoroutineContext = kotlin.coroutines.coroutineContext
        val otherCoroutineContext = (dfe.graphQlContext.get(CoroutineScope::class) as CoroutineScope).coroutineContext
    }
}

These two CoroutineContext objects are not the same.

The documentation states:

In order to preserve coroutine context, we need to populate GraphQLContext map with a CoroutineScope that should be used to execute any suspendable functions

(https://opensource.expediagroup.com/graphql-kotlin/docs/schema-generator/execution/async-models#structured-concurrency)

Do I understand it correct that I should use the CoroutineContext from the DataFetchingEnvironment to start a new coroutine and NOT the given current CoroutineContext object?

Which coroutine context or better coroutine scope should I use, if I would like to start a coroutine in parallel so that the response goes back immediately without waiting for the result? Does it still make sense to use this scope: https://api.ktor.io/ktor-server/ktor-server-core/io.ktor.server.application/-application/index.html?

@samuelAndalon
Copy link
Contributor

use the coroutine scope from the graphQLContext which is located in the dataFetchingEnvironment, most of the time you DO NOT need to explicitly run coroutines in parallel, the coroutines state machine is smart enough to decide if a new thread needs to be use to launch a new coroutine.

@cndev123
Copy link

cndev123 commented Jul 17, 2024

I also did a bit of further research:
The coroutine scope in the dfe is the parent scope of the scope that the resolver functions run in. So, the Job object in kotlin.coroutines.coroutineContext is the child of the Job object in (dfe.graphQlContext.get(CoroutineScope::class) as CoroutineScope).coroutineContext.

If you need to start something that truely runs in parallel, i.e. return early with the response to the client but keep working on something on the server, you have to use a different scope; not the one mentioned above. Because both scopes/jobs/contexts have a lifetime that is bound to the handling of this one graphQL call; i.e. they are not suited to start something that runs longer than the call handling.

I think https://api.ktor.io/ktor-server/ktor-server-core/io.ktor.server.application/-application/index.html is good option for something like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants