Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Constructing backpressure-aware OnSubscribe classes one onNext at a time? #1930

@akarnokd

Description

@akarnokd

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions