Мятеж: восстановление после единственного тайм-аута
Из приложения quarkus (kotlin) я запрашиваю несколько конечных точек (одна и та же конечная точка, но с другим базовым URL) параллельно, а затем комбинирую uni, чтобы не ждать последовательно каждого ответа.
Вот пример:
val unis = repository.findUnis()
?.sites
?.map { site ->
RestClientBuilder.newBuilder()
.baseUri(URI.create(site.url))
.build(MyClientService::class.java)
.api("param")
.ifNoItem()
.after(Duration.ofMillis(1))
.recoverWithItem(null)
.onFailure()
.invoke {
logger.info("Error while connecting to ${site.url}", it)
}
.onFailure()
.recoverWithItem(null as? String)
}
return Uni.combine().all().unis<String>(unis)
.combinedWith { it as (List<String?>?) }
.await().atMost(Duration.ofMillis(1))
?.filterNotNull()
Проблема в том, что
ifNoItem
не используется в случае тайм-аута. Если один uni занимает более 1 миллисекунды (это значение только для тестов...), то последний блок генерирует исключение TimeoutException в
combinedWith(...).await()
.
Я хотел бы обработать тайм-аут на уровне единого модуля, и эту ошибку следует рассматривать как сбой (и регистрировать ее и восстанавливать). Но, похоже, это не работает. Моя реализация взята из https://smallrye.io/smallrye-mutiny/#_how_do_i_handle_timeout).
Как это правильно делать?
1 ответ
Вместо
.ifNoItem().after(Duration.ofMillis(1)).recoverWithItem(null)
, используйте:.ifNoItem().after(Duration.ofMillis(1).fail()
который будет распространять неудачу.