Как добиться той же функциональности, что и повтор, с помощью оператора repeatWhen или repeatWhenEmpty при объединении с webClient - PullRequest
0 голосов
/ 08 марта 2020

Лог повторов c реализован в WebClientConfig.ExchangeFilterFunction . Я хотел бы реализовать подобное с оператором repeatWhenEmpty.

Использование:

  • Java 1.8
  • Версия загрузочной пружины 2.1X
  • Project Reactor Addons 3.1.6

Конфигурация:

@Slf4j
@Configuration
public class WebClientConfig {

     private static final String host = "https://google.com";  //test host

     @Bean
     public WebClient retryingClient(WebClient.Builder builder) {
        return builder
              .baseUrl(host)
              .filter(retryFilter())
              .build();
     }

     private ExchangeFilterFunction retryFilter() {
          AtomicInteger counter = new AtomicCounter();

          return ((request, next) ->
              next.exchange(request)
                  .log()
                  .doOnNext(clientResponse -> {
                       log.info(Request: {} {}", request.method(), request.url());

                       HttpStatus status = clientResponse.statusCode();

                       if (status == HttpStatus.ACCEPTED) { //retry if the client returns 202
                            counter.incrementAndGet();
                            log.info("Retrying : {}", counter.get());
                            throw new RetryException("Retrying - " + counter.get());
                       } else if (status.isError()) {
                            log.info("Error, status code : {}", clientResponse.statusCode);
                            throw new RuntimeException("Status code : " + clientResponse.statusCode);
                       }
                  }).retryWhen(Retry.anyOf(RetryException.class)
                    .exponentialBackoff(Duration.ofMillis(100), Duration.ofMillis(500))
                    .retryMax(4));
      }
}

Это служба, которая использует настроенный выше веб-клиент.

@Service
@Slf4j
public class ExternalCallService {
     private final WebClient webClient;
     private static final String path = "/flights";  //test url

     public ExternalCallService(@Qualifier("retryingClient") WebClient webClient) {
          this.webClient = webClient;
     }

     public Flux<String> fetchFlights(String query) {
          return webClient
                .get()
                .uri(uri -> uri.path(path).queryParam("filter", query).build())
                .exchange()
                .flatMap(response -> response.bodyToFlux(String.class));

    }

}

Исключение времени выполнения, чтобы помочь триггер повтор

public class RetryException extends RuntimeException {
     public RetryException(String msg) {
          super(msg);
     }
}

Примечание. Я в основном набираю этот код здесь, извините за опечатку или пропущенную точку с запятой (если есть). Я постараюсь добавить больше деталей, если это необходимо.

1 Ответ

0 голосов
/ 09 марта 2020

Это то, что вы ищете?

.repeatWhen(emitted -> emitted
        .zipWith(Flux.range(1, 4)) // do repeat 4 times
        .flatMap(t -> Mono
                // exponential backoff, you can play around this
                // to get a desired backoff value
                .delay(Duration.ofMillis(100 * t.getT2()))
        )
)
...