You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Came across some weird behavior while using methods doOnSubscribe and doOnUnsubscribe of Observable. The reason being that those methods use operators OperatorDoOnSubscribe & OperatorDoOnUnsubscribe.
publicclassOperatorDoOnSubscribe<T> implementsOperator<T, T> {
privatefinalAction0subscribe;
/** * Constructs an instance of the operator with the callback that gets invoked when the modified Observable is subscribed * @param subscribe the action that gets invoked when the modified {@link rx.Observable} is subscribed */publicOperatorDoOnSubscribe(Action0subscribe) {
this.subscribe = subscribe;
}
@OverridepublicSubscriber<? superT> call(finalSubscriber<? superT> child) {
subscribe.call();
// Pass through since this operator is for notification only, there is// no change to the stream whatsoever.returnchild;
}
}
publicclassOperatorDoOnUnsubscribe<T> implementsOperator<T, T> {
privatefinalAction0unsubscribe;
/** * Constructs an instance of the operator with the callback that gets invoked when the modified Observable is unsubscribed * @param unsubscribe The action that gets invoked when the modified {@link rx.Observable} is unsubscribed */publicOperatorDoOnUnsubscribe(Action0unsubscribe) {
this.unsubscribe = unsubscribe;
}
@OverridepublicSubscriber<? superT> call(finalSubscriber<? superT> child) {
child.add(Subscriptions.create(unsubscribe));
// Pass through since this operator is for notification only, there is// no change to the stream whatsoever.returnchild;
}
}
These operators when passed on to lift in Observable, get wrapped inside a new Observable which on subscription passes the incoming Subscriber to the provided operator and then call onStart of the returned Subscriber. Since essentially the above mentioned operators just return the incoming subscriber, there is a possibility of onStart getting called multiple times (which has the potential to mess up backpressure)
intcount = 100; // Should be > 16 for Android & > 128 for other platformsObservable
.from(getIntegerList(count))
.doOnSubscribe(newOnSubscribeAction())
.observeOn(Schedulers.io())
.flatMap(newFlatMapFunc())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
newPrivateSubscriber(
(TextView) findViewById(R.id.backpressure_missing_text)
)
);
In the above code, observeOn (operator OperatorObserveOn) applies backpressure by request(RxRingBuffer.SIZE) in onStart of the Subscriber it creates and returns. When OperatorDoOnSubscribe gets lifted, it also calls onStart of the same subscriber which again make a request for RxRingBuffer.SIZE items. So when a Producer gets set, it sees that RxRingBuffer.SIZE * 2 items got requested and will start emitting. But if it happens to be faster than its consumer, will result in MissingBackpressureException
Relevant code from OperatorObserveOn
@OverridepublicvoidonNext(finalTt) {
if (isUnsubscribed()) {
return;
}
// The `queue` that `OperatorObserveOn` uses is bound to `RxRingBuffer.SIZE`if (!queue.offer(on.next(t))) {
onError(newMissingBackpressureException());
return;
}
schedule();
}
A complete Android application to reproduce the issue is @ Backpressure test
The text was updated successfully, but these errors were encountered:
Came across some weird behavior while using methods
doOnSubscribe
anddoOnUnsubscribe
ofObservable
. The reason being that those methods use operatorsOperatorDoOnSubscribe
&OperatorDoOnUnsubscribe
.These operators when passed on to
lift
inObservable
, get wrapped inside a newObservable
which on subscription passes the incomingSubscriber
to the provided operator and then callonStart
of the returnedSubscriber
. Since essentially the above mentioned operators just return the incoming subscriber, there is a possibility ofonStart
getting called multiple times (which has the potential to mess up backpressure)PARTIAL CODE TO REPRODUCE
In the above code,
observeOn
(operatorOperatorObserveOn
) applies backpressure byrequest(RxRingBuffer.SIZE)
inonStart
of theSubscriber
it creates and returns. WhenOperatorDoOnSubscribe
gets lifted, it also callsonStart
of the same subscriber which again make a request forRxRingBuffer.SIZE
items. So when aProducer
gets set, it sees thatRxRingBuffer.SIZE * 2
items got requested and will start emitting. But if it happens to be faster than its consumer, will result inMissingBackpressureException
Relevant code from
OperatorObserveOn
A complete Android application to reproduce the issue is @ Backpressure test
The text was updated successfully, but these errors were encountered: