如果出错,请再次拨打电话并在webflux中重试

时间:2019-04-30 16:03:35

标签: java spring spring-webflux spring-webclient

我想使用spring webflux中的WebClient执行以下操作:

  • 致电endpoint1
  • 如果失败并出现预期错误,则
    • 致电endpoint2
    • 仅重试endpoint1一次

我已经走了这么远:

webclient.get()
  .uri("/endpoint1")
  .retrieve()
  .bodyToFlux(MyBody.class)
  .retry(error -> {
     if (error == expectedError) {
       webclient.get()
         .uri("/endpoint2")
         .retrieve().block();
       return true;
     } else {
       false;
     });

请求endpoint2时无法阻止,因为会出现以下错误:block()/blockFirst()/blockLast() are blocking, which is not supported in thread(我也不想阻止)。

也许我应该使用retryWhen,但我不确定如何使用它。

1 个答案:

答案 0 :(得分:1)

我做这项工作的唯一方法是与retryWhen一起使用,因为它只接受reactor.retry.Retry#doOnRetry而不是ConsumerMono,所以我不能使用FluxPublisher

代码段如下:

webclient.get()
  .uri("/endpoint1")
  .retrieve()
  .bodyToFlux(MyBody.class)
  .retryWhen(errorCurrentAttempt -> errorCurrentAttempt
                .flatMap(currentError -> Mono.subscriberContext().map(ctx -> Tuples.of(currentError, ctx)))
                .flatMap(tp -> {
                    Context ctx = tp.getT2();
                    Throwable error = tp.getT1();
                    int maxAttempts = 3;
                    Integer rl = ctx.getOrDefault("retriesLeft", maxAttempts);
                    if (rl != null && rl > 0 && error == myExpectedError) {
                        // Call endpoint and retry
                        return webclient.get()
                                .uri("/endpoint2")
                                .retrieve()
                                .thenReturn(ctx.put("retriesLeft", rl - 1));
                    } else {
                        // Finish retries
                        return Mono.<Object>error(error);
                    }
                }));