Модификация ktors вызывает контекстную подпрограмму - PullRequest
1 голос
/ 06 мая 2019

Итак, я использую ktor и хочу, чтобы некоторые данные были доступны по всему контексту через ThreadLocal. Я смотрю на это:

val dataThreadLocal = ThreadLocal<String>()
suspend fun fromOtherFunction() = "From other function -- ${dataThreadLocal.get()}"

routing {
    get("/hello") {
        // [1]
        launch(this.coroutineContext + dataThreadLocal.asContextElement(value = "world")) {
            val fromHere = async {
                "ThreadLocal value: ${dataThreadLocal.get()}"
            }

            val fromThere = async {
                fromOtherFunction()
            }

            call.respond(fromHere.await() + "," + fromThere.await())
        }

    }
}

Что я делаю, так это чтобы все и любые функции, вызываемые из родительского элемента launch (помеченные [1]), имели доступ к данным такого рода "scoped".

Однако мое приложение довольно большое, и я хочу, чтобы это работало для всех запросов, обрабатываемых маршрутизацией, и не хочу, чтобы каждый маршрут требовал такой обертки.

Что было бы действительно здорово:

intercept(ApplicationCallPipeline.Features) {
    launch(this.coroutineContext + dataThreadLocal.asContextElement(value = "world")) {
    ...
    }
}

routing {
    get("/hello") {
        val threadLocalValue = dataThreadLocal.get()
    ...

Что, очевидно, не работает, поскольку область сопрограмм в intercept не включает область сопрограмм маршрута.

То, что я считаю, происходит из-за того, что каждый вызов запускается в родительской подпрограмме (аналогично тому, как у нас есть «потоки запросов»). Есть ли способ изменить контекст в этом? Есть ли способ, где я могу сказать ApplicationEngine - + дополнительный элемент контекста всякий раз, когда запускается этот новый контекст совместной программы?

...