Jakub Gwóźdź
07/13/2022, 8:28 AMsuspend fun main() = withContext(MDCContext(mapOf("host" to "local"))) {
val ktorClient = HttpClient(OkHttp)
log("entering context")
(1..10).forEach { i ->
val newContextMap = MDC.getCopyOfContextMap()
newContextMap["i"] = i.toString()
withContext(MDCContext(newContextMap)) {
log("before calling ktor client $i")
ktorClient.get { url("<https://example.com/$i>") }.bodyAsText()
log("after calling ktor client $i")
}
}
log("exiting context")
ktorClient.close()
}
when run, the MDC is shuffled totally indeterministic:
10:21:45.238 [main] - entering context {host=local}
10:21:45.240 [main] - before calling ktor client 1 {host=local, i=1}
10:21:45.824 [DefaultDispatcher-worker-1] - after calling ktor client 1 {}
10:21:45.824 [DefaultDispatcher-worker-1] - before calling ktor client 2 {host=local, i=2}
10:21:45.998 [DefaultDispatcher-worker-1] - after calling ktor client 2 {}
10:21:45.998 [DefaultDispatcher-worker-1] - before calling ktor client 3 {host=local, i=3}
10:21:46.102 [DefaultDispatcher-worker-1] - after calling ktor client 3 {host=local}
10:21:46.103 [DefaultDispatcher-worker-1] - before calling ktor client 4 {host=local, i=4}
10:21:46.208 [DefaultDispatcher-worker-3] - after calling ktor client 4 {}
...
But as soon as I change first line to
suspend fun main() = withContext(Dispatchers.Default + MDCContext(mapOf("host" to "local"))) {
it magically starts working as intended. (same on any other dispatcher, IO or Unconfined)
Why is it so? Is it a problem with suspend fun main
, ktor-client, or - most probably - me messing up something here?Robert Williams
07/13/2022, 9:21 AMsuspend fun main
, just search this chat and you'll find plenty of unexpected behaviour related to its Dispatcher implementationJakub Gwóźdź
07/13/2022, 9:27 AMktorClient.get {}
with
launch(<http://Dispatchers.IO|Dispatchers.IO>) { Thread.sleep(200) }
I still get the suspension, still get the thread switching, but MDC stays correct.
Basically, I cannot reproduce the behaviour without ktor, even if I strongly elieve the problem is within suspend fun main
🙂Joffrey
07/13/2022, 9:33 AMI still get the suspension, still get the thread switching, but MDC stays correct
<http://Dispatchers.IO|Dispatchers.IO>
shares threads with Dispatchers.Default
so you might not effectively be switching threads here. You might reproduce with a custom dispatcher.Jakub Gwóźdź
07/13/2022, 9:34 AMJoffrey
07/13/2022, 9:34 AM(1..10).forEach { i ->
, you can use repeat(10) { i ->
which is easier to read IMO (however indexing will be 0-based)Joffrey
07/13/2022, 9:36 AMaccording to logs, the entries are on different threadsOk, it might be because you use more threads than what is available in
DIsptachers.Default
so eventually it does create other threadsJakub Gwóźdź
07/13/2022, 9:36 AMJoffrey
07/13/2022, 9:36 AMit’s not the point anywayIt was just a side remark indeed
Jakub Gwóźdź
07/13/2022, 9:37 AMlaunch(<http://Dispatchers.IO|Dispatchers.IO>) { Thread.sleep(200) }
instead of ktor client: (notice MDC is correct here while threads switch)
11:24:30.535 [main] - entering context {host=local}
11:24:30.537 [main] - before calling ktor client 1 {host=local, i=1}
11:24:30.537 [main] - after calling ktor client 1 {host=local, i=1}
11:24:30.744 [DefaultDispatcher-worker-1] - before calling ktor client 2 {host=local, i=2}
11:24:30.745 [DefaultDispatcher-worker-1] - after calling ktor client 2 {host=local, i=2}
11:24:30.951 [DefaultDispatcher-worker-3] - before calling ktor client 3 {host=local, i=3}
11:24:30.952 [DefaultDispatcher-worker-3] - after calling ktor client 3 {host=local, i=3}
Joffrey
07/13/2022, 9:38 AMsuspend fun main
. Recently I discovered that it didn't have a Job
(which makes sense, because Job
is from kotlinx-coroutines
) but that means coroutineContext.isActive
returns false, unintuitively. There definitely may be other weird things with `suspend fun main`'s coroutine context.Joffrey
07/13/2022, 9:39 AMsuspend fun main() = withContext()
without dispatcher there works?Jakub Gwóźdź
07/13/2022, 9:40 AMJoffrey
07/13/2022, 9:40 AMJakub Gwóźdź
07/13/2022, 9:40 AMJoffrey
07/13/2022, 9:41 AMRobert Williams
07/13/2022, 9:49 AMRobert Williams
07/13/2022, 9:49 AMRobert Williams
07/13/2022, 9:51 AMJakub Gwóźdź
07/13/2022, 9:52 AMsuspend fun main
? 🙂Robert Williams
07/13/2022, 9:53 AMRobert Williams
07/13/2022, 11:22 AM