I try to zip two Monos into one, like in the following example.
final Mono<String> mono1 = ...;
final Mono<String> mono2 = ...;
final Mono<String> result = Mono.zip(mono1, mono2)
.map(args -> args.getT1() + ":" + args.getT1());
My expectation now is, that mono2 is not evaluated if mono1 is an error-Mono, but this is not always the case. It seems that mono2 is evaluated, even in the case of an error, if it is the result of a Mono::flatMap operation. The following test will reproduce this behaviour.
@Test
public void shortCircuitZip() {
final var count = new AtomicInteger();
// Short-circuting in zip if first is an error-mono.
final var mono1 = Mono.zip(
Mono.<String>error(new IllegalArgumentException("Illegal")),
Mono.fromSupplier(() -> {
count.incrementAndGet();
return "RESULT";
})
)
.map(args -> "%s:%s".formatted(args.getT1(), args.getT2()));
assertThatThrownBy(mono1::block).isInstanceOf(IllegalArgumentException.class);
assertThat(count.get()).isEqualTo(0);
// If the second mono has a 'flatMap' in it, the zip is no longer
// short-circuting.
final var mono2 = Mono.zip(
Mono.<String>error(new IllegalArgumentException("Illegal")),
Mono.fromSupplier(() -> {
count.incrementAndGet();
return "RESULT";
})
.flatMap(v -> Mono.just(v))
)
.map(args -> "%s:%s".formatted(args.getT1(), args.getT2()));
assertThatThrownBy(mono2::block).isInstanceOf(IllegalArgumentException.class);
// This assertion fails with a "flatMapped" second mono.
assertThat(count.get()).isEqualTo(0);
}
The question is, whether this behaviour is intentional or a bug in the reactor library?
I'm using the following reactor version: io.projectreactor:reactor-core:3.4.19