使用重试策略时 Uni 订阅不是 运行

Uni subscription not running when using retry policy

我在 Quarkus 中使用 Mutiny 时遇到了一些奇怪的行为。

我的问题是我正在尝试将现有方法包装到 Uni 中,我希望此方法重试一定次数,如果它们都失败了,我希望调用我的失败订阅,但是没有。

为了更好的理解这一点,我为它写了一个测试:

@Test
void mutinySubscriptionNotCalledAfterRetry() {
    final AtomicBoolean executed = new AtomicBoolean(false);
    Uni.createFrom().item(this::error)
       .onFailure()
       .retry()
       .withBackOff(Duration.ofSeconds(1)).withJitter(0.2)
       .atMost(5)
       .subscribe()
       .with(success -> fail(),
             failure -> executed.set(true));
    assertTrue(executed.get()); // Failing statement
}

private boolean error() {
    throw new RuntimeException();
}

问题是失败订阅永远不会 运行,我不知道我是否没有理解某些东西,但根据 Clement 的游乐场,这似乎是一个有效的用例:

https://gist.github.com/cescoffier/e9abce907a1c3d05d70bea3dae6dc3d5

任何人都可以阐明这一点吗?

非常感谢。

用例完全有效,但您的测试编写不正确。这种重试是异步的。因此,执行断言时尚未调用失败回调 (failure -> execute(set(true));)。你需要等到它被调用。在您的情况下,大约需要 35 秒。

要等待,您可以使用 Awaitility 并执行如下操作:await().until(() -> executed.get());。您也可以使用 io.smallrye.mutiny.helpers.test.UniAssertSubscriber:

@Test
void mutinySubscriptionNotCalledAfterRetry() {
  UniAssertSubscriber<Boolean> subscriber = 
    Uni.createFrom().item(this::error)              
       .onFailure().retry()
          .withBackOff(Duration.ofSeconds(1)).withJitter(0.2)
          .atMost(5)
       .subscribe().withSubscriber(new UniAssertSubscriber<>());

  subscriber.awaitFailure(Duration.ofSeconds(35));
}

private boolean error() {
    throw new RuntimeException("boom");
}