Мятеж: восстановление после единственного тайм-аута

Из приложения 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() который будет распространять неудачу.

Другие вопросы по тегам