-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Description
Guava features the AbstractIterable
that basically implements a state machine under the hood to support creating elements on demand. One has to implement one method only that computes the next value or signals termination, which allows constructing iterables more easily (Java lacks yield return & yield break). Now if one can express his/her computation in this way, the backpressure is freely available through Observable.from
. I had to do this the hard way for OperatorRetryTest.FuncWithErrors
I wonder if it is possible to create an abstract builder "dual" of AbstractIterable
? The difficulty lies in the fact that onError
and onCompleted
are not subject to backpressure so having a simple callback for the next value is not enough since its completely legal to emit onNext+onCompleted for a single requested value. As with AbstractIterable
it might be unavoidable to buffer at least one onNext() value.
For example:
static class State {
int phase;
int calls;
}
AbstractOnSubscribe<Integer, State> aos = new AbstractOnSubscribe<Integer, State>() {
// create a per-subscriber state, a more global state may be captured as usual
@Override
protected State onSubscribe(Subscriber s) {
return new State();
}
// release a per-subscriber state
@Override
protected void onTerminated(State state) {
}
// what should be next?
// once this returns, the downstream will receive the value if requested
@Override
protected void onNext(State state) {
switch (state.phase) {
case 0:
onNext("Beginning");
if (state.calls < 128) {
onError(new RuntimeException());
} else {
state.phase = 1;
}
case 1:
onNext("Beginning"); // no exception this time
state.phase = 2;
case 2:
onNext("Finally succeeding");
onCompleted();
state.phase = 3;
default:
}
state.calls++;
}
}
We might support buffering directly in this AbstractOnSubscribe
(but that effectively duplicates the onBackpressureBuffer() behavior so easy to forget to add to a chain).