【发布时间】:2023-04-08 20:24:01
【问题描述】:
我有一个 Spring Boot 应用程序,其中包含一个复杂的反应流(它涉及 MongoDB 和 RabbitMQ 操作)。大多数时候它都有效,但是......
一些方法返回Mono<Void>。这是一个典型的模式,有多个层次:
fun workflowStep(things: List<Thing>): Mono<Void> =
Flux.fromIterable(things).flatMap { thing -> doSomethingTo(thing) }.collectList().then()
假设doSomethingTo() 返回一个Mono<Void>(它将某些内容写入数据库,发送消息等)。如果我只是用Mono.empty() 替换它,那么一切都会按预期工作,否则不会。更具体地说, Mono 永远不会完成,它会运行所有处理,但最后会错过终止信号。所以事情实际上是写在数据库中,消息是实际发送的等等。
为了证明缺少终止是问题所在,这里有一个可行的技巧:
val hackedDelayedMono = Mono.empty<Void>().delayElement(Duration.ofSeconds(1))
return Mono.first(
workflowStep(things),
hackedDelayedMono
)
问题是,我可以用从未完成的 Mono 做些什么来弄清楚发生了什么?我无处可以放置日志语句或刹车点,因为:
- 没有错误
- 没有信号发出
如何检查 Mono 正在等待完成的内容?
ps。我无法使用简单的 Mono 工作流程在应用程序之外重现此行为。
【问题讨论】:
-
从函数返回
Mono#empty将具有返回类型Mono<Void>,这意味着您需要向我们展示doSomething中的内容。您很可能在某处断开了链条,但您尚未发布可重复的工作示例,因此无法判断您在哪里断开链条。 -
“hackedDelayedMono”上的延迟实际上并没有做任何事情,因为延迟只发生在元素上而不是信号上。由于它是一个空单声道,它将直接在订阅时完成。
标签: spring-boot spring-webflux project-reactor