So far we have a feign client which in case of exception, we used to retry as below
Retryer<ClientResponse> retryer = RetryerBuilder.<ClientResponse>newBuilder()
.retryIfExceptionOfType(FeignException.class)
.withStopStrategy(StopStrategies.stopAfterAttempt(retryCount))
.withWaitStrategy(WaitStrategies.exponentialWait(maxWaitSeconds, TimeUnit.SECONDS))
.build();
retryer.call(() -> {
return client.doStuffs(someInput); }
);
recently I tried moving from this custom retryer to an inbuilt feign retryer as below :
Feign client = Feign.builder()
.decoder(jacksonDecoder)
.encoder(jacksonEncoder)
.logger(slf4jLogger)
.client(okHttpClient)
.retryer(new Retryer.Default(
SECONDS.toMillis(minWaitSeconds),
SECONDS.toMillis(maxWaitSeconds),
retryCount
))
.requestInterceptor(new BasicAuthRequestInterceptor(clientConfig.getUser(), clientConfig.getPassword()))
.target(target);
client.doStuffs(someInput);
understanding was that feign client itself would be taking care of exception but apparently, that's not the case, the minute client throws a 5xx
, I get an exception with no retries.
Is there something else needed for the implementation to retry?
this service is in dropwizard, git and SO threads are mostly around spring / ribbon which is not the case with me.
dep
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>${feign.version}</version>
</dependency>
Without additional configuration, Feign will retry on IOException
s only. If you wish to retry based on status codes, you will need to create an ErrorDecoder
that throws a RetryableException
or derivative of, in order to trigger a retry.
Here is simple example:
class MyErrorDecoder implements ErrorDecoder {
public Exception decode(String methodKey, Response response) {
if (response.status() == 503) {
throw new RetryableException(
response.status(),
"Service Unavailable",
response.request().httpMethod(),
null);
} else {
return new RuntimeException("error");
}
}
}
For more examples, take a look at the Error Handling documentation.