Получение исключения ResponseAlreadySentException после попытки ответить на объекты ApplicationCall, переданные через поток состояний

#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"

Заранее благодарим вас за любую информацию, которую вы можете предложить.