What is the best way to handle this situation: I’m launching a coroutine using some CoroutineDispatcher (let’s say CommonPool) which “takes” the ContinuationInterceptor key. Now I also have some context information, let’s say a request id, which I want to set on the SLF4j Mapped Diagnostic Context (MDC) when the continuation resumes. MDC is thread bound and I was thinking of using a ContinuationInterceptor context, but I now realize that it won’t compose with the CoroutineDispatcher (since the key is already taken).
Should I create my own CoroutineDispatcher that implements both behaviors?
Just to give an idea this is an example of what I came up with
class RequestContext(
val reqId: String
) : AbstractCoroutineContextElement(RequestContext) {
companion object Key: CoroutineContext.Key<RequestContext>
}
object MyPool : CoroutineDispatcher() {
private val pool = ForkJoinPool((Runtime.getRuntime().availableProcessors() - 1).coerceAtLeast(1))
override fun dispatch(context: CoroutineContext, block: Runnable) {
pool.execute {
val reqCtx = context[RequestContext.Key]
if (reqCtx != null) {
MDC.put("reqId", reqCtx.reqId)
}
block.run()
}
}
}
fun main(args: Array<String>) {
val log = LoggerFactory.getLogger("test")
runBlocking {
val ja = launch(MyPool + RequestContext("A")) {
log.info("A1")
delay(10)
log.info("A2")
delay(10)
log.info("A3")
delay(10)
log.info("A4")
}
val jb = launch(MyPool + RequestContext("B")) {
log.info("B1")
delay(10)
log.info("B2")
delay(10)
log.info("B3")
delay(10)
log.info("B4")
}
ja.join()
jb.join()
}
}
Wondering if there is a way to avoid having to define my own CoroutineDispatcher