https://kotlinlang.org logo
#ktor
Title
# ktor
a

Antonio Acuña Prieto

03/09/2024, 5:29 PM
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

Aleksei Tirman [JB]

03/11/2024, 7:38 AM
What do you mean by blocking threads?
a

Antonio Acuña Prieto

03/11/2024, 7:47 AM
Threads meant to do blocking operations like db queries
a

Aleksei Tirman [JB]

03/11/2024, 8:26 AM
The Dispathers.IO dispatcher is designed for offloading blocking IO tasks to a shared pool of threads.
a

Antonio Acuña Prieto

03/11/2024, 8:58 AM
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

Aleksei Tirman [JB]

03/11/2024, 10:05 AM
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

Antonio Acuña Prieto

03/11/2024, 10:19 AM
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

Aleksei Tirman [JB]

03/11/2024, 10:28 AM
Where the
EngineMain
object is imported from?
a

Antonio Acuña Prieto

03/11/2024, 10:28 AM
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

Aleksei Tirman [JB]

03/12/2024, 8:58 AM
In the block of the
testApplication
, I observe the following coroutine context:
Copy code
[CoroutineId(1), "coroutine#1":BlockingCoroutine{Active}@42530531, BlockingEventLoop@5a3bc7ed]
a

Antonio Acuña Prieto

03/12/2024, 9:08 AM
Yep, and if you look in a route, the context is Dispatchers IO instead of Default Netty
a

Aleksei Tirman [JB]

03/12/2024, 9:28 AM
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

Antonio Acuña Prieto

03/12/2024, 9:30 AM
Nice! I will try, thank you