【问题标题】:Retry Logic in case of failure - Spring Reactor失败时重试逻辑 - Spring Reactor
【发布时间】:2017-05-10 04:39:15
【问题描述】:

我如何对 RetryWhen 进行单元测试,

 public Mono<List<Transaction>> get(String id) {
            return class
                    .get(id).log()
                 .retryWhen(throwableFlux -> throwableFlux) 
                .zipWith(Flux.range(min, max + 1), (error, retry) -> new RetryException(error, retry))
                .flatMap(retryException -> {
                    if(retryException.getRetries() == max + 1) {
                        throw Exceptions.propagate(retryException.getThrowable());
                    } else if (isClientException(retryException.getThrowable())){
                        return Flux.empty();
                    }
                    return Mono.delay(Duration.ofMinutes( new Double(multiplier * retryException.getRetries()).longValue()));
                }));
        }

如何使用 StepVerifier 来测试这个方法?

实现重试逻辑的另一种方式,

throwableFlux.takeWhile(throwable -> !isClientException(throwable))
            .flatMap(e -> {
                if(count.get() >= max + 1) {
                    throw Exceptions.propagate(e);
                }
                LOG.info("Retrying in..");
                return Mono.delay(Duration.ofMinutes(new Double(multiplier * count.getAndAdd(1)).longValue()));
            });

【问题讨论】:

  • retryWhen 行上没有额外的右括号吗?您正在将 zipWith.flatMap 应用于throwableFlux,对吗?

标签: spring project-reactor


【解决方案1】:

您的意思是测试通过retryWhen 应用的RetryHelper

你当然可以用StepVerifier来测试这样的retryWhen包含序列,是的。您还可以通过在 retryWhen 之前使用与 doOnSubscribe 耦合的 AtomicLong 来检查(重新)订阅的数量(这将有助于确定对正在重试的源的订阅数量)。

请注意,我们刚刚为 retryWhenrepeatWhen 添加了这样一个构建器实用程序,但在 reactor-extra project 中(当前在 3.1.0.BUILD-SNAPSHOT 中)

【讨论】:

  • 哎呀。我只是扩展了代码。我能够使用 stepverifier.withVirtualTime 测试我的代码。我在特定条件下返回 Flux.empty() - (no-op)。有没有关于如何测试的建议?
  • 测试一个空的但有限的通量就像verifyComplete() 一样简单,之前没有任何期望低于expectSubscription
  • FirstStep.verifyComplete() 或 type.expectSubscription().verifyComplete() 都卡在 DefaultStepVerifierBuilder.pollTask​​EventOrComplete 中的无限 for 循环中。
  • 啊,如果您使用虚拟时间,您可能仍然需要通过 thenAwaitexpectNoEvent 提前时钟(我想您在链中添加了延迟和重试,这恰好发生在由于其他运营商而最终为空?)
  • 是的。那是正确的。因为如果没有在某种类型的错误上提前时钟,我没有调用 expectNoEvent。谢谢。
【解决方案2】:

这就是我能够测试此代码的方式。

FirstStep.expectSubscription().expectNoEvent(java.time.Duration.ofMinutes(1)).expectNoEvent(Duration.ofMinutes(3)).verifyError()

我们可以在上面使用 thenAwait(Duration.ofDays(1)),但是 expectNoEvent 的好处是保证什么都没有发生 早于它应该有的。

http://projectreactor.io/docs/core/snapshot/reference/docs/index.html#error.handling

【讨论】:

    猜你喜欢
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 2019-02-23
    • 2023-03-07
    • 2021-11-22
    • 1970-01-01
    • 2017-04-20
    • 2021-09-25
    相关资源
    最近更新 更多