Итак, я использую 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
- +
дополнительный элемент контекста всякий раз, когда запускается этот новый контекст совместной программы?