Search code examples
javaspringmonoproject-reactorflux

Repeat Mono with webclient from SpringFlux


The Situation is the following: I sent the first request, then I sent repeatedly the second request with interval 5s. If the second request takes the success response, I save it in the database and do some actions, if it takes the not success(complete) response the request should be repeated. I need to stop repeating the second request when attempts will be bigger than 3. How I can do this?

     return firstRequestSenderService.send(request)
        .flatMap(resp -> {
          AtomicInteger attempts = new AtomicInteger(0);
          String url = normalizeUrl(resp.getResult());
          return Mono.defer(() -> {
            log.info("Second request, attempt = {}, params = {}", attempts.get(), param);
            return secondRequestSenderService.send(param, url, attempts.getAndIncrement());
          })
              .filter(this::isCompleteResponse)
              // i try .filter(b -> attempts.get() > 2)
              .doOnNext(r -> log.info("Save report"))
              .map(secondResp -> dataSaver.saveReport(param, secondResp))
              .doOnNext(r -> log.info("Send request to another service"))
              .flatMap(r -> secondRequestSender.sendPdf(r)))
              .doOnNext(bytes -> dataSaver.saveAnotherReport(param, bytes))
              .repeatWhenEmpty(req -> Flux.interval(Duration.ofSeconds(5)));
// also try   .repeatWhenEmpty(3, req -> Flux.interval(Duration.ofSeconds(5)));
        })
        .then(Mono.empty());

Solution

  • check reactor-addons you can do something like that

        return firstRequestSenderService.send(request)
            .flatMap(resp -> {
              return secondRequestSenderService
                      .send(param, url, attempts.getAndIncrement())
                      .retryWhen(Retry.any()
                              .randomBackoff(Duration.ofMillis(100), Duration.ofMillis(5000))
                              .retryMax(3));
    
            });
    

    also u can do that with reactor core retry utils RetryBackoffSpec you will get that when you use latest spring webflux

      RetryBackoffSpec retryBackoffSpec = Retry
            .fixedDelay(3, Duration.ofSeconds(5));
    return firstRequestSenderService.send(request)
            .flatMap(resp -> {
                      return secondRequestSenderService
                              .send(param, url, attempts.getAndIncrement())
                              .retryWhen(retryBackoffSpec);
                    });