MyrionSC2
MyrionSC2

Reputation: 1318

Access CoroutineContext element via Key class

In Ktor, I am hoping to implement some way to reference key value pairs inside a coroutineContext, without dragging references to objects around in method parameters. Based on https://proandroiddev.com/demystifying-coroutinecontext-1ce5b68407ad I have written my reference classes:

class MyElement(override val key: CoroutineContext.Key<*>, val value: String) : CoroutineContext.Element
class MyKey: CoroutineContext.Key<MyElement>

... // inside routing:

val key: CoroutineContext.Key<MyElement> = MyKey()
val ele = MyElement(key, "myJWT")
withContext(coroutineContext + ele) {
    val notNullEle : MyElement = coroutineContext[ele.key] as MyElement // not null
    logger.info(notNullEle.value) // "myJWT"
    val shouldNotBeNullEle = coroutineContext[MyKey()]// NULL!
}
val shouldBeNull = coroutineContext[ele.key] // is and should be null
val shouldBeNull2 = coroutineContext[MyKey()] // is and should also be null

When I send ele.key to coroutineContext[ele.key] I get the right element, but when I send a new instance of MyKey along, I get null, so the instance of MyElement is clearly mapped to the instance of the key. That does not work well for my purposes however, as I was hoping to get the instance of MyElement using the class of MyKey, since I would like to be able to, for instance, get the value in a HttpClient in the service layer without having to pass ele.key all the way down the chain. Is it possible?

What I am asking is basically the same as How to make request-bound data globally available in Ktor? which is unfortunately unanswered.

Upvotes: 1

Views: 2193

Answers (1)

Kiskae
Kiskae

Reputation: 25573

As described in the article you linked, you could consider the CoroutineContext to be a Map with CoroutineContext.Key as its keys.

Given this premise the problem you are having is clear, ele.key != MyKey() or the keys are not equivalent by definition, so they will not return the same entry within the context Map.

This is the reason why most CoroutineContext.Key implementations are object, because that implements the equals method based on the object singleton. You will either need to also use object or correctly implement equals and hashCode.

Upvotes: 6

Related Questions