【发布时间】:2021-11-10 17:44:48
【问题描述】:
我试图了解如果您订阅带有几个变体的 Mono.error(new OutOfMemoryError("hello world")) 会发生什么。
我通过了这些测试(使用 reactor-core 3.4.3):
@Test
public void oom() {
Mono.error(new OutOfMemoryError("hello world")).subscribe();
}
@Test
public void oom_thenReturn() {
try {
Mono.error(new OutOfMemoryError("hello world")).thenReturn(123).subscribe();
fail("Expected OOMError");
} catch (OutOfMemoryError e) {
// expected
}
}
@Test
public void oom_then_thenReturn() {
Mono.error(new OutOfMemoryError("hello world")).then().thenReturn(123).subscribe();
}
@Test
public void genericError_thenReturn() {
Mono.error(new Error("hello world")).thenReturn(123).subscribe();
}
因此,如果您订阅Mono.error(new OutOfMemoryError("hello world")).thenReturn(123),它会在订阅线程上引发异常。但是如果你省略了thenReturn(123) 调用,在它之前添加一个额外的then() 调用,或者使用通用的Error 而不是OutOfMemoryError,订阅线程上不会抛出异常。 (如果您添加日志记录 Subscriber,您会看到 onSubscribe 和 onError 被按预期调用。)
我知道为什么OutOfMemoryError 会与Error 受到不同的处理,但我不明白为什么thenReturn(123) 调用会导致错误传播到订阅线程,而并非如此。谁能解释一下?
【问题讨论】:
-
我对reactor不太熟悉,但是由于异步性,您的测试是否会在抛出异常之前完成?也许你应该打电话给
block()而不是subscribe()? -
确实所有
block()调用都会在这种情况下抛出。但是,上述行为是 100% 可重现的(至少对我而言),所以它看起来不像是竞争条件。 -
另外,如果我使用
StepVerifier,那么我会看到相同的模式:StepVerifier.create(Mono.error(new OutOfMemoryError("hello world"))).expectError().verify()通过,但使用StepVerifier.create(Mono.error(new OutOfMemoryError("hello world")).thenReturn(123)).expectError().verify(),verify()调用会抛出OutOfMemoryError。 (据我了解,StepVerifier旨在消除竞争条件。)
标签: java project-reactor