В случае ошибки сделайте еще один вызов и повторите попытку в webflux
Я хотел бы сделать следующее, используя WebClient
с весны webflux:
- Вызов
endpoint1
- Если это не удается с ожидаемой ошибкой, то
- вызов
endpoint2
а также - повторить попытку
endpoint1
только однажды
- вызов
Я получил это далеко:
webclient.get()
.uri("/endpoint1")
.retrieve()
.bodyToFlux(MyBody.class)
.retry(error -> {
if (error == expectedError) {
webclient.get()
.uri("/endpoint2")
.retrieve().block();
return true;
} else {
false;
});
Я не могу заблокировать при запросе endpoint2
так как я получил бы следующую ошибку: block()/blockFirst()/blockLast() are blocking, which is not supported in thread
(Я бы тоже не хотел блокировать).
Может быть, я должен использовать retryWhen
но я не совсем уверен, как его использовать.
1 ответ
Решение
Единственный способ, которым я сделал эту работу, был с retryWhen
Я не мог использовать reactor.retry.Retry#doOnRetry
потому что он принимает только Consumer
не Mono
или же Flux
или же Publisher
,
Фрагмент выглядит следующим образом:
webclient.get()
.uri("/endpoint1")
.retrieve()
.bodyToFlux(MyBody.class)
.retryWhen(errorCurrentAttempt -> errorCurrentAttempt
.flatMap(currentError -> Mono.subscriberContext().map(ctx -> Tuples.of(currentError, ctx)))
.flatMap(tp -> {
Context ctx = tp.getT2();
Throwable error = tp.getT1();
int maxAttempts = 3;
Integer rl = ctx.getOrDefault("retriesLeft", maxAttempts);
if (rl != null && rl > 0 && error == myExpectedError) {
// Call endpoint and retry
return webclient.get()
.uri("/endpoint2")
.retrieve()
.thenReturn(ctx.put("retriesLeft", rl - 1));
} else {
// Finish retries
return Mono.<Object>error(error);
}
}));