#kotlin #kotlin-coroutines #ktor #kotlin-stateflow
#kotlin #kotlin-сопрограммы #ktor #kotlin-поток состояний
Вопрос:
Я тестирую архитектуру, управляемую событиями, в KTOR. Моя основная логика хранится в классе, который реагирует на различные типы событий, передаваемых потоком состояний. Генераторы событий помещают события в поток состояний, которые улавливаются ядром.
Однако, когда ядро пытается ответить на ApplicationCall
встроенное в одно из моих событий, я получаю ResponseAlreadySentException
, и я не уверен, почему это так. Этого не произойдет, если я обойду поток состояний и вызову базовый класс непосредственно из EventGenerator . Я не отвечаю на вызовы applicationcall где-либо еще в моем коде и проверил с помощью точек останова, что единственная .respond
строка не попадает несколько раз.
Класс MyStateFlow:
class MyStateFlow {
val state: StateFlow<CoreEvent>
get() = _state
private val _state = MutableStateFlow<CoreEvent>(CoreEvent.NothingEvent)
suspend fun update(event: CoreEvent) {
_state.value = event
}
}
Мой основной класс:
class Core(
myStateFlow: MyStateFlow,
coroutineContext: CoroutineContext = SupervisorJob() Dispatchers.IO
) {
init {
CoroutineScope(coroutineContext).launch {
myStateFlow.state.collect {
onEvent(it)
}
}
}
suspend fun onEvent(event: CoreEvent) {
when(event) {
is FooEvent {
event.call.respond(HttpStatusCode.OK, "bar")
}
...
}
}
}
Одним из моих генераторов событий является маршрут в моем классе приложений KTOR:
get("/foo") {
myStateFlow.update(CoreEvent.FooEvent(call))
}
Однако нажатие /f00
в моем браузере возвращает либо сообщение an ResponseAlreadySentException
, либо сообщение java.lang.UnsupportedOperationException
with: «Заголовки больше не могут быть установлены, поскольку ответ уже завершен». Ответ об ошибке может переключаться между ними, пока я пытаюсь найти разные попытки решения, но, похоже, они говорят одно и то же: на вызов уже был дан ответ до того, как я попытаюсь позвонить call.respond(...)
.
Если я вместо этого изменю свой маршрут, чтобы вызвать Core.onEvent()
напрямую, нажатие /foo
возвращает «bar» в моем браузере, как и предполагаемое поведение:
get("/foo") {
core.onEvent(CoreEvent.FooEvent(call))
}
Для полноты мои версии зависимостей:
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.10"
implementation "io.ktor:ktor-server-netty:1.4.1"
Заранее благодарим вас за любую информацию, которую вы можете предложить.