Sarvar Nishonboyev
Sarvar Nishonboyev

Reputation: 13080

Spring Webclient retry and execute a code if all retries are exhausted

I have a webhook service that sends events to different sources (URLs). By design, the request timeout is 10s, if it fails, retries to send 3 times. In case, all retries are failed, a code must be executed to disable that URL in DB.

So far, I managed to retry and with delay of 5 seconds. But, I'm not sure how to execute code after failure.

    try{

          String body = objectMapper.writeValueAsString(webhookDTO);

                webClient.post()
                        .uri(webhook.getUrl())
                        .contentType(MediaType.APPLICATION_JSON)
                        .bodyValue(body)
                        .exchange()
                        .timeout(Duration.ofSeconds(5))
                        .retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
                                .jitter(0d)
                                .doAfterRetry(retrySignal -> {
                                    logger.info("Retried " + retrySignal.totalRetries());
                                })
                                .onRetryExhaustedThrow((retryBackoffSpec, retrySignal) 
                                                    -> new WebhookTimeoutException()))
                        .doOnSuccess(clientResponse -> {
                            logger.info("Event is received by " + client);
                        })
                        .subscribe();
            } catch (Exception e) {
                logger.error("Error on webhook dispatcher: ", e);
            }

Can anyone give some examples of how to do this?

Upvotes: 8

Views: 18387

Answers (1)

vins
vins

Reputation: 15370

You are almost there! Just use doOnError as shown here. The idea here, once after all the attempts failed, you throw WebhookTimeoutException. The doOnError is called only when the error is thrown & updates the DB. The exception class is optional. You can ignore that.

webClient.post()
        .uri(webhook.getUrl())
        .contentType(MediaType.APPLICATION_JSON)
        .bodyValue(body)
        .exchange()
        .timeout(Duration.ofSeconds(5))
        .retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
                .jitter(0d)
                .doAfterRetry(retrySignal -> {
                    logger.info("Retried " + retrySignal.totalRetries());
                })
                .onRetryExhaustedThrow((retryBackoffSpec, retrySignal) 
                                    -> new WebhookTimeoutException()))
        .doOnSuccess(clientResponse -> {
            logger.info("Event is received by " + client);
        })
        .doOnError(WebhookTimeoutException.class, (msg) -> {
            System.out.println("Message :: " + msg);
            // here update the DB
            dbRepository.save(...);
        })        
        .subscribe();

Upvotes: 8

Related Questions