我想做的是在有webclient的Webflux中的Mono上有条件地重复。情况如下:
我们有一些商务休息服务服务,可返回生成的文档。此文档的生成是由在此之前调用的另一服务触发的。但是,回到正题:文档生成服务需要10到30秒。我们想要做的是:10秒钟后检查是否生成文档(单声道)。如果是这样,一切都很好。如果不是,请在5秒钟后重复(或重试)并检查是否生成了文档。依此类推,直到(最坏的情况)直到30秒后超时。这可能吗?一些(伪)代码:
return this.webClient.post().uri(SERVICE_URL)). body(BodyInserters.fromObject(docRequest)).retrieve(). bodyToMono(Document.class). delaySubscription(Duration.ofSeconds(10)). repeat5TimesWithDynamicTimeDelayUntil(!document.isEmpty()). subscribe();
格蕾兹·伯纳多
是的,有可能。
Mono 有两个用于重新订阅(因此,重新触发请求)的概念
Mono
每个概念都有Mono针对不同用例的多种重载方法。寻找retry*和repeat*方法。例如,要无延迟重试最大次数,请使用retry(int numRetries)。
retry*
repeat*
retry(int numRetries)
通过retryWhen和repeatWhen方法支持更复杂的用例,如以下示例所示。
retryWhen
repeatWhen
要重试单声道是否异常完成最多5次,每次尝试之间间隔5秒:
// From reactor-core >= v3.3.4.RELEASE import reactor.util.retry.Retry; this.webClient .post() .uri(SERVICE_URL) .body(BodyInserters.fromValue(docRequest)) .retrieve() .bodyToMono(Document.class) .retryWhen(Retry.fixedDelay(5, Duration.ofSeconds(5))) .delaySubscription(Duration.ofSeconds(10))
重试构建器支持其他退避策略(例如指数)和其他选项,以完全自定义重试。
请注意,retryWhen(Retry)上面使用的方法已添加到反应堆核心v3.3.4.RELEASE中,并且retryWhen(Function)不建议使用该方法。在reactor- core v3.3.4.RELEASE之前,您可以使用reactor- extras项目中的重试功能构建器来创建一个Function传递给retryWhen(Function)。
retryWhen(Retry)
retryWhen(Function)
Function
如果您需要成功重复一次,请使用.repeatWhen或.repeatWhenEmpty代替.retryWhen上面的内容。
.repeatWhen
.repeatWhenEmpty
.retryWhen
使用reactor- extras项目中的重复函数构建器来创建重复Function,如下所示:
// From reactor-extras import reactor.retry.Repeat; this.webClient .post() .uri(SERVICE_URL) .body(BodyInserters.fromValue(docRequest)) .retrieve() .bodyToMono(Document.class) .filter(document -> !document.isEmpty()) .repeatWhenEmpty(Repeat.onlyIf(repeatContext -> true) .exponentialBackoff(Duration.ofSeconds(5), Duration.ofSeconds(10)) .timeout(Duration.ofSeconds(30))) .delaySubscription(Duration.ofSeconds(10))
如果要重新订阅成功或失败,也可以将a .retry*与a 链接在一起.repeat*。
.retry*
.repeat*