When .timeout(Duration.ofSeconds(requestTimeout)) happens below message is printed
ERROR [parallel-6] com.www.xyz.bbb.restv2retry.RestV2ServiceImpl:888 – Did not observe any item or terminal signal within 80000ms in ‘retryWhen’ (and no fallback has been configured)
i get the message because timout has occured while calling api to some server and response did not came back,but i want to retry when timeout occurs so inside retryPolicy() method i used condition || throwable.getCause() instanceof TimeoutException to retry when timeout occurs but still not working.
Any idea how to retry after timeout happens ?
Below is the code
@Service
public class RestV2ServiceImpl implements RestV2Service {
private static final Logger LOGGER = LoggerFactory.getLogger(RestV2ServiceImpl.class);
@Value("${apirest.server.requestTimeoutInSeconds}")
private Long requestTimeout;
@Value("${retryPolicy.maxAttempts}")
private Integer restV2retryPolicyMaxAttempts;
@Value("${retryPolicy.periodInMilliseconds}")
private Long restV2initialInterval;
@Autowired
private WebClient webClient;
@Override
public String updateRequestV2(String url, String requestJson, String versionSequence) {
return webClient.patch()
.uri(url)
.header(HttpHeaders.CONTENT_TYPE, "application/json-patch+json")
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.header("If-Match", versionSequence)
.body(BodyInserters.fromValue(requestJson))
.retrieve()
.onStatus(this::retryableStatuses, this::retryableStatusException)
.bodyToMono(String.class)
.retryWhen(retryPolicy())
.timeout(Duration.ofSeconds(requestTimeout))
.doOnError(throwable -> LOGGER.error(throwable.getMessage()))
.block();
}
/**
* Return the range of HTTP codes for which REST v2 requests should be retried.
* @param status HttpStatus returned from a REST call
* @return true if request should be retried
*/
private boolean retryableStatuses(HttpStatus status) {
return status.is5xxServerError();
}
/**
* Creates an exception to be analyzed by the "retryWhen(...)" method to indicate
* conditions for which a request should be retried.
* @param response HTTP response from the latest REST request
* @return
*/
private Mono<? extends Throwable> retryableStatusException(ClientResponse response) {
return response.bodyToMono(String.class).map(body ->
new HttpServerErrorException(response.statusCode(), body));
}
/**
* Defines the policy for retrying a REST request.
* This policy retries on HttpServerErrorException created by the retryableStatusException
* method (which defines retryable server side errors) and on WebClientRequestException which defines
* client side errors prior to processing a request (e.g. certain request timeouts).
* @return the policy
*/
private Retry retryPolicy() {
return Retry.backoff(restV2retryPolicyMaxAttempts, Duration.ofMillis(restV2initialInterval))
.filter(throwable -> throwable instanceof HttpServerErrorException || throwable instanceof WebClientRequestException || || throwable.getCause() instanceof TimeoutException)
.onRetryExhaustedThrow(((retryBackoffSpec, retrySignal) -> new RetryExhaustedException(retrySignal.failure().getMessage())));
}
}
Need to retry even if timeout occurs