question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Provide a way to propagate a custom context to CoroutineContext

See original GitHub issue

Currently, CoroutineContext could be customized with AbstractCoroutineServerImpl constructor. https://github.com/grpc/grpc-kotlin/blob/2f3d86b661894d2047c98ca8082932dffc8378d1/stub/src/main/java/io/grpc/kotlin/AbstractCoroutineServerImpl.kt#L29

And it is combined with GrpcContextElement that captures a context from the current thread and propagates it. https://github.com/grpc/grpc-kotlin/blob/2f3d86b661894d2047c98ca8082932dffc8378d1/stub/src/main/java/io/grpc/kotlin/ServerCalls.kt#L199

However, a CoroutinContext injected by users could not propagate any context from the current thread, because it was instantiated when the Coroutine stub is created.

We can use a hack that was suggested by @anuraaga, https://github.com/line/armeria/pull/2669#issuecomment-615269862

internal object ArmeriaContext: CoroutineContext {
    override fun <R> fold(initial: R, operation: (R, CoroutineContext.Element) -> R): R =
            EmptyCoroutineContext.fold(initial, operation)

    override fun <E : CoroutineContext.Element> get(key: CoroutineContext.Key<E>): E? =
            EmptyCoroutineContext.get(key)

    override fun minusKey(key: CoroutineContext.Key<*>): CoroutineContext =
            EmptyCoroutineContext.minusKey(key)

    override fun plus(context: CoroutineContext): CoroutineContext {
        val requestCtx: RequestContext = RequestContext.current()
        return requestCtx.contextAwareExecutor().asCoroutineDispatcher() + context
    }
}

We don’t think this is a nice approach. If AbstractCoroutineServerImpl get CoroutineContext from a method then constructor parameter, gRPC-Kotlin users can easily propagate their context to CoroutineContext.

abstract class AbstractCoroutineServerImpl(
        val defaultContext: CoroutineContext = EmptyCoroutineContext
) : BindableService {
    open fun context(): CoroutineContext = defaultContext
}

class UserService: XXXCoroutineImplBase() {
    override fun context(): CoroutineContext {
        return ServiceRequestContext.current().contextAwareExecutor().asCoroutineDispatcher()
    }
}

Do you think this change makes sense, I could make a PR. 😀

/cc @anuraaga

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:15 (3 by maintainers)

github_iconTop GitHub Comments

7reactions
lowassercommented, Jul 15, 2020

Merged a mechanism to introduce CoroutineContext elements via an interceptor – which can also be easily installed on multiple servers, which seem applicable to many of these use cases.

3reactions
lowassercommented, Jun 12, 2020

I’m moving forward on a design for an interceptor-based solution, where interceptors can inject CoroutineContext elements. There’s no ambiguity about how they work, what information they have access to, or other thread-local information.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Coroutine context and dispatchers - Kotlin
coroutines provides. It has one key limitation, though: when a thread-local is mutated, a new value is not propagated to the coroutine caller...
Read more >
How to propagate kotlin coroutine context through reflective ...
There are reasons i'm writing a custom implementation which i don't need to get into. Everything's based on suspending functions and coroutines ...
Read more >
What is CoroutineContext and how does it work? - Kt. Academy
CoroutineContext is part of the built-in support for Kotlin coroutines, so it is imported from kotlin.coroutines , while contexts like Job or CoroutineName...
Read more >
Coroutine Context and Dispatchers | Baeldung on Kotlin
3.1. How to Manipulate a Coroutine Context? CoroutineContext is immutable, but we can have a new context by adding an element, removing one, ......
Read more >
Demystifying CoroutineContext - ProAndroidDev
The CoroutineScope receiver is defined by the way it provides a CoroutineContext . This is the inherited context. The builder function receives ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found