Да, это возможно.
Mono
имеет две концепции для повторной подписки (и, следовательно, повторного запуска запроса)
- retry = повторная подписка, если восходящий поток завершен с исключением
- повтор = повторная подписка, если восходящий поток успешно завершен
Каждая концепция имеет несколько перегруженных методов в Mono
для разных вариантов использования. Ищите методы retry*
и repeat*
.
Например, обычный вариант использования - это повторная попытка с использованием стратегии экспоненциального отката с помощью retryBackoff
.
.
Более сложные варианты использования поддерживаются через retryWhen
и repeatWhen
. Проект реактор-дополнительные включает в себя несколько сборщиков, которые помогут вам построить функции для перехода к этим методам.
Вот пример, который повторяется, если моно завершено с исключением максимум 5 раз с 5 секундами между каждой попыткой
this.webClient
.post()
.uri(SERVICE_URL)
.body(BodyInserters.fromObject(docRequest))
.retrieve()
.bodyToMono(Document.class)
.retryWhen(Retry.any()
.fixedBackoff(Duration.ofSeconds(5))
.retryMax(5))
.delaySubscription(Duration.ofSeconds(10))
Существуют другие стратегии возврата (например, экспоненциальный) и другие параметры, доступные для полной настройки повторных попыток (например, использование тайм-аута вместо максимального количества повторных попыток).
Если вам нужно повторить в случае успеха, используйте .repeatWhen(Repeat...)
или .repeatWhenEmpty(Repeat...)
вместо .retryWhen(Retry...)
выше. Например:
this.webClient
.post()
.uri(SERVICE_URL)
.body(BodyInserters.fromObject(docRequest))
.retrieve()
.bodyToMono(Document.class)
.filter(document -> !document.isEmpty())
.repeatWhenEmpty(Repeat.onlyIf(repeatContext -> true)
.exponentialBackoff(Duration.ofSeconds(5), Duration.ofSeconds(10))
.timeout(Duration.ofSeconds(30)))
.delaySubscription(Duration.ofSeconds(10))
Вы также можете связать .retry*
с .repeat*
, если хотите повторно подписаться как на успех, так и на неудачу.