Hello, I'm using Ktor with Netty and JDBI. I want ...
# ktor
a
Hello, I'm using Ktor with Netty and JDBI. I want to make db request in blocking threads, how can I do it? I just noticed that all inside a route is actually using Dispatchers.IO so it's really necessary to do db requests in blocking threads?
a
What do you mean by blocking threads?
a
Threads meant to do blocking operations like db queries
a
The Dispathers.IO dispatcher is designed for offloading blocking IO tasks to a shared pool of threads.
a
What surprised me is the fact that all inside a Ktor route is running using Dispatchers.IO tbh, I expected to run on default dispatcher and move to IO dispatcher manually when you are going to perform blocking tasks
a
How did you determine that? I can see the following coroutine context in the route's handler:
Copy code
[io.ktor.server.engine.DefaultUncaughtExceptionHandler@7cf0fc5c, CoroutineName(call-handler), io.ktor.server.netty.NettyDispatcher$CurrentContext@c180069, StandaloneCoroutine{Active}@341891db, NettyDispatcher@4fe0efc1]
What server engine do you use?
a
Example:
Copy code
fun main(args: Array<String>) = EngineMain.main(args)

fun Application.routingModule() {
    routing {
        get {
            this.call.respond(HttpStatusCode.OK) // breakpoint here
        }
    }
}
The context is:
Copy code
[io.ktor.client.engine.KtorCallContextElement@4714d20c, CoroutineName(request), kotlinx.coroutines.UndispatchedMarker@6e311309, io.opentelemetry.extension.kotlin.KotlinContextElement@354937d4, PluginsTrace(), UndispatchedCoroutine{Active}@5842a908, <http://Dispatchers.IO]|Dispatchers.IO]>
Ok, other example with a fresh project:
Copy code
[io.ktor.server.engine.DefaultUncaughtExceptionHandler@54faf79e, CoroutineName(call-handler), io.ktor.server.netty.NettyDispatcher$CurrentContext@8f50c428, kotlinx.coroutines.UndispatchedMarker@1f0fc589, PluginsTrace(), UndispatchedCoroutine{Active}@a1e0de4f, NettyDispatcher@cdc429ee]
It seems like something I'm doing is moving all my requests to IO dispatcher, am I right?
a
Where the
EngineMain
object is imported from?
a
Copy code
import io.ktor.server.netty.*
In both examples
I'll debug today what happens, maybe one plugin or anything is causing this behaviour, I'll send updates later, thanks
Ok, found the issue, when you debug the tests created with
testApplication
its Dispatchers.IO, when you debug the app running it gets
NettyDispatcher
Is there something we could do here? @Aleksei Tirman [JB] It’s a bit weird for me that the app runs different in testing than in production.
a
In the block of the
testApplication
, I observe the following coroutine context:
Copy code
[CoroutineId(1), "coroutine#1":BlockingCoroutine{Active}@42530531, BlockingEventLoop@5a3bc7ed]
a
Yep, and if you look in a route, the context is Dispatchers IO instead of Default Netty
a
Starting from Ktor
3.0.0-beta-1
, you can override the default dispatcher. Here is an example:
Copy code
@Test
fun test() = testApplication {
    engine {
        dispatcher = Dispatchers.Default
    }

    application {
        routing {
            post {
                println(coroutineContext)
                call.respondText { "POST" }
            }
        }
    }

    // ...
}
👍 1
a
Nice! I will try, thank you