您如何在Project Reactor中实现轮询逻辑?

时间:2019-06-10 00:41:25

标签: spring project-reactor

我有一个发送请求以获取作业状态并返回状态的方法,它看起来像这样:

Mono<JobStatus> getJobStatus() {...}

JobStatus对象具有方法JobStatus.isDone(),该方法返回是否完成挂起的作业。

JobStatus.isDone()为真之前,有没有办法让我继续订阅单声道?即类似getJobStatus().keepSubscribingUntil(status -> status.isDone())

2 个答案:

答案 0 :(得分:2)

一种选择是让getJobStatus() Mono仅在完成工作时发出,这可能不一定容易,具体取决于当前实现Mono的方式。

对于轮询,假设每次订阅Mono时进行轮询,您可以将repeatWhentakeUntil配对使用:

getJobStatus()
    .repeatWhen(iter -> Mono.delay(Duration.ofMillis(pollDelay))) //(1)
    .takeUntil(JobStatus::isDone) //(2)
    .last() //(3)

(1)反复重新订阅源Mono(这会产生Flux<JobStatus>

(2)一旦返回的状态标记为完成,就取消上述重复周期

(3)切换回Mono<JobStatus>,它发出上一次迭代的状态(因此标记为已完成的状态)

答案 1 :(得分:0)

其他选项可能会使用 repeatWhenEmpty ,当您可能想轮询直到获得发布者的成功或失败时。在某些情况下,您不想永远等待以获得响应,而不想超时,可以使用具有自己逻辑或库方法使操作超时的相同方法。

AtomicInteger c = new AtomicInteger();
Mono<String> source = Mono.defer(() -> c.getAndIncrement() < 3 
? Mono.empty() 
: Mono.just("7"));
return source.repeatWhenEmpty(4, Flux::cache);

在上面的示例4中,指定了您要重试的最大次数。

source.repeatWhenEmpty(exponentialBackOff(Duration.ofMillis(1), 
                Duration.ofMillis(15),
                Duration.ofSeconds(1)));

https://github.com/cloudfoundry/cf-java-client具有exponentialBackOff实用程序方法。