GT-Sandbox-Snapshot: Example adding Request ID to Co-Routine Context.
Code
package com.glassthought.sandboximport com.glassthought.sandbox.util.out.impl.outimport kotlinx.coroutines.*import kotlin.coroutines.AbstractCoroutineContextElementimport kotlin.coroutines.CoroutineContextimport kotlin.coroutines.coroutineContext// Define a context element to hold request IDdata class RequestId(val id: String) : AbstractCoroutineContextElement(RequestId) { companion object Key : CoroutineContext.Key<RequestId>}// Any suspend function can access the request ID from contextsuspend fun doWork(about: String) { val requestId = currentCoroutineContext()[RequestId]?.id out.info("[${about}]: Working on request_id=[$requestId]") delay(50)}fun main(): kotlin.Unit = runBlocking { println("--------------------------------------------------------------------------------") println("MAIN started") // Add request ID to coroutine context withContext(RequestId("req-12345")) { out.info("Request ID added to context") // All suspend calls in this scope can access it doWork("direct-call-within-context") // Child inherits parent context (RequestId + CoroutineName) launch { doWork("in-launch") } }}
Command to reproduce:
gt.sandbox.checkout.commit 86fa348a8e09123d80d8 \&& cd "${GT_SANDBOX_REPO}" \&& cmd.run.announce "./gradlew run --quiet"
Recorded output of command:
Picked up JAVA_TOOL_OPTIONS: -Dkotlinx.coroutines.debugPicked up JAVA_TOOL_OPTIONS: -Dkotlinx.coroutines.debug--------------------------------------------------------------------------------MAIN started[INFO][elapsed: 15ms][①][coroutname:@coroutine#1] Request ID added to context[INFO][elapsed: 27ms][①][coroutname:@coroutine#1] [direct-call-within-context]: Working on request_id=[req-12345][INFO][elapsed: 81ms][⓶][coroutname:@coroutine#2] [in-launch]: Working on request_id=[req-12345]
NOTE: if you launch on another scope as expected the fields will NOT transfer over UNLESS you pass through your coroutine context.
GT-Sandbox-Snapshot: Example passing through custom element to a task spawned on background scope.
Code
package com.glassthought.sandboximport kotlinx.coroutines.*import kotlin.coroutines.AbstractCoroutineContextElementimport kotlin.coroutines.CoroutineContextdata class RequestId(val id: String) : AbstractCoroutineContextElement(RequestId) { companion object Key : CoroutineContext.Key<RequestId>}suspend fun doWork(about: String) { val requestId = currentCoroutineContext()[RequestId]?.id println("[$about]: request_id=[$requestId]") delay(50)}// Different scope (like a singleton or background processor)val backgroundScope = CoroutineScope(Dispatchers.Default)fun main() = runBlocking { println("=== Context Inheritance ===\n") withContext(RequestId("req-12345")) { println("Request context set to: req-12345\n") // ✅ INHERITS - uses current scope launch { doWork("launch") } // ❌ DOES NOT INHERIT - uses backgroundScope instead backgroundScope.launch { doWork("backgroundScope.launch") } // ✅ FIX - explicitly pass context to different scope backgroundScope.launch(currentCoroutineContext()) { doWork("backgroundScope.launch + context") } delay(200) } backgroundScope.cancel()}
Command to reproduce:
gt.sandbox.checkout.commit 052b2be0dc8e73ae2259 \&& cd "${GT_SANDBOX_REPO}" \&& cmd.run.announce "./gradlew run --quiet"
Recorded output of command:
Picked up JAVA_TOOL_OPTIONS: -Dkotlinx.coroutines.debugPicked up JAVA_TOOL_OPTIONS: -Dkotlinx.coroutines.debug=== Context Inheritance ===Request context set to: req-12345[backgroundScope.launch]: request_id=[null][launch]: request_id=[req-12345][backgroundScope.launch + context]: request_id=[req-12345]