Could I be able to add multiple retryWhen
to perform retries to handle different WebClient failure responses?
What I want to achieve:
I am using WebClient to make REST API Calls. There are few error scenarios, when happens I need to perform retry, but with different delays.
For eg,
1. if 401 Unauthorize
happens, I can retry immediately after refreshing the token.
2. If 502/503 Server
error happens, I need to delay the retries after 5 sec.
3. if 429 Too Many Request
happens, I need to delay the retry little longer, say 20sec after.
I would like to create Retry spec like below:
protected static final Predicate<Throwable> is401 =
(throwable) -> throwable instanceof WebClientResponseException.Unauthorized;
protected static final Predicate<Throwable> is5xx =
(throwable) -> throwable instanceof WebClientResponseException.ServiceUnavailable;
protected static final Predicate<Throwable> is429 =
(throwable) -> throwable instanceof WebClientResponseException.TooManyRequests;
Retry retry401 = Retry.fixedDelay(5, Duration.ofSeconds(1))
.filter(is401)
.onRetryExhaustedThrow((retryBackoffSpec, retrySignal) -> retrySignal.failure());
Retry retry5xx = Retry.fixedDelay(5, Duration.ofSeconds(10))
.filter(is5xx)
.onRetryExhaustedThrow((retryBackoffSpec, retrySignal) -> retrySignal.failure());
Retry retry429 = Retry.fixedDelay(5, Duration.ofSeconds(20))
.filter(is429)
.onRetryExhaustedThrow((retryBackoffSpec, retrySignal) -> retrySignal.failure());
// trying to apply the to WebClient like below:
WebClient.Builder()
.get()
.uri("endpointuri")
.retrieve()
.bodyToFlux(String.class)
.retryWhen(retry401)
.retryWhen(retry5xx)
.retryWhen(retry429);
Looks like `.retryWhen(retry429)' overwrites the other retries.
Looks like `.retryWhen(retry429)' overwrites the other retries.
This is false. retryWhen
is a composite operator that builds upon the existing publisher - you can chain it as many times as you like. The only time you need to worry about one retry "overriding" another is when your filter
predicates overlap.
Even in this case, it looks like it's "first wins" (in the chain) not "last wins".
Your problems instead may be to do with this line:
protected static final Predicate<Throwable> is5xx =
(throwable) -> throwable instanceof WebClientResponseException.ServiceUnavailable;
From your naming and your description, it looks like you want this to catch any 5xx error - but it'll only catch 503 (which is specifically assigned to "service unavailable".)
If you're trying with something different, like a 502 or 500 error - then none of the predicates (and therefore retries) you've defined will match.
Instead, to check for any 5xx error, you likely want:
protected static final Predicate<Throwable> is5xx =
(throwable) -> throwable instanceof WebClientResponseException && ((WebClientResponseException)throwable).getStatusCode().is5xxServerError();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With