I'm not sure if this is a coroutines question or a...
# coroutines
x
I'm not sure if this is a coroutines question or a ktor question... We were using ktor's
EngineMain
, but needed to do some even earlier initialization (place some things in MDC globally), so we switched to using the embedded server. Our
main
function ended up looking something like:
Copy code
fun main() {
    val config = getConfig()
    runBlocking() {
        setupGlobalMDC(config)
        withContext(MDCContext()) {
            embeddedServer(Jetty, port = config.port) {

                // The stuff in here used to be in the function
                // referenced by ktor.application.modules
                val backgroundJob = launch { backgroundWorker() }
                serverSetup(config, backgroundJob)

            }.start(wait = true)
        }
    }
}
This mostly worked, except it turned out that
backgroundJob
didn't seem to be running. It's a loop that listens on a channel, and somehow it did not seem to be doing anything even when messages were sent to its channel. It worked fine before we switched to using the embedded server. On a hunch, I tried replacing
runBlocking()
with
runBlocking(<http://Dispatchers.IO|Dispatchers.IO>)
. Now it works, but I don't really understand why it didn't work in the first place. Does anyone know why
<http://Dispatchers.IO|Dispatchers.IO>
is required here?
d
I don't know much about Ktor, but I know about the behavior of `runBlocking`: by default, it uses a single-threaded coroutine dispatcher, so if something in the server was hogging the thread, there is no opportunity for the background job to execute. If you specify a multi-threaded dispatcher explicitly, the background job can execute independently.
By the way, you don't have to specify the dispatcher for the whole
runBlocking
, you can also pass it to
launch
. Then only that job will execute on another dispatcher.
c
Hi! This is not related to Ktor, nor Coroutines… None of the Ktor functions you are calling here are
suspend
, so you shouldn't need
runBlocking
at all. My guess is
serverSetup
is
suspend
, but you didn't send its code so I can't tell.
x
(I just realized that this message has been in my drafts for over a month. Sorry for the late reply, I thought I'd already sent it.) Yes,
serverSetup
is
suspend
. Additionally,
embeddedServer
is a extension function on
CoroutineScope
. In the real code the launch is actually inside that function. I think your answer gave me a better idea about what's going on, and why using
<http://Dispatchers.IO|Dispatchers.IO>
"fixes" it, though it also makes me think that's not really the correct way to accomplish this. I looked in ktor's EngineMain, and saw that it seems to use construct a dispatcher out of Jetty's thread pool. Unfortunately, there doesn't seem to be any way to mimic this when using
embeddedServer
. However, I saw that
embeddedServer
has an overload that uses
GlobalScope
, so I tried switching to that, and it works as desired. Thank you both!