I have the following code:
Flux<String> flux = Flux.<String>never()
.doOnRequest(n -> System.out.println("Requested " + n));
It is a Flux that never emits any signal, but reports demand to the console.
Each of the following 3 lines
flux.take(3).next().block();
flux.next().block();
flux.blockFirst();
produces this output:
Requested 9223372036854775807
Looking at the code, I see the following.
BlockingSingleSubscriber
(works both in the cases of Flux#blockFirst()
and Mono#block()
:
public final void onSubscribe(Subscription s) {
this.s = s;
if (!cancelled) {
s.request(Long.MAX_VALUE);
}
}
MonoNext.NextSubscriber
:
public void request(long n) {
if (WIP.compareAndSet(this, 0, 1)) {
s.request(Long.MAX_VALUE);
}
}
FluxTake.TakeSubscriber
:
public void request(long n) {
if (wip == 0 && WIP.compareAndSet(this, 0, 1)) {
if (n >= this.n) {
s.request(Long.MAX_VALUE);
} else {
s.request(n);
}
return;
}
s.request(n);
}
So Flux#blockFirst()
, Flux#next()
and Mono#block()
always signal an unbounded demand to their upstream, and Flux#take()
can do the same under some circumstances.
But Flux#blockFirst()
, Flux#next()
and Mono#block()
each need at max one element from their upstream, and Flux#take()
needs maximally this.n.
Also, Flux#take()
javadoc says the following:
Note that this operator doesn't manipulate the backpressure requested amount. Rather, it merely lets requests from downstream propagate as is and cancels once N elements have been emitted. As a result, the source could produce a lot of extraneous elements in the meantime. If that behavior is undesirable and you do not own the request from downstream (e.g. prefetching operators), consider using {@link #limitRequest(long)} instead.
The question is: why do they signal an unbounded demand when they know the limit upfront? I had an impression that reactive backpressure was about only asking for what you are ready to consume. But in reality, it often works like this: shout 'produce all you can' to the upstream, and then cancel the subscription once satisfied. In cases when it is costly to produce gazillion records upstream this seems simply wasteful.