ContinuationInterceptor composability


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)

fun main(args: Array<String>) {
  val log = LoggerFactory.getLogger("test")
  runBlocking {
    val ja = launch(MyPool + RequestContext("A")) {"A1")

    val jb = launch(MyPool + RequestContext("B")) {"B1")


Wondering if there is a way to avoid having to define my own CoroutineDispatcher