Spring Webclient повторяет попытку и выполняет код, если все попытки исчерпаны - PullRequest
1 голос
/ 05 апреля 2020

У меня есть служба webhook, которая отправляет события в разные источники (URL). По умолчанию время ожидания запроса составляет 10 с, в случае сбоя повторная отправка отправляется 3 раза. В случае неудачи всех повторных попыток необходимо выполнить код, чтобы отключить этот URL в БД.

Пока мне удалось повторить попытку с задержкой в ​​5 секунд. Но я не уверен, как выполнить код после сбоя.

    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);
            }

Кто-нибудь может привести несколько примеров, как это сделать?

1 Ответ

1 голос
/ 05 апреля 2020

Вы почти у цели! Просто используйте doOnError, как показано здесь. Идея тут, однажды после всех попыток провалилась, вы кидаете WebhookTimeoutException. DoOnError вызывается только тогда, когда выдается ошибка и обновляется БД. Класс исключения является необязательным. Вы можете игнорировать это.

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();
...