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
This may be a problem with MapObserver or OnErrorResumeXXX and is probably related to #216
If the function returned by OnErrorResumeXXX returns an async Observable then there is some unpredictable behavior with operators (eg Map) that rely on the AtomicObserver to generate a valid event stream
I've created a UnitTest below to demonstrate the problem.
@TestpublicvoidtestMapError() {
Observable<String> observable = Observable.from("one","error","two","three");
Observable<String> m = Observable.create(map(observable, newFunc1<String,String>() {
@OverridepublicStringcall(Stringin) {
if ("error".equals(in))
thrownewRuntimeException("Simulated error");
returnin;
}
}));
// Add error handlerm=m.onErrorResumeNext(newFunc1<Exception,Observable<String>>() {
publicObservable<String> call(Exceptione) {
returncreateSlowSequence(newString[] {"II","III"});
}
});
m.subscribe(stringObserver);
verify(stringObserver, times(1)).onNext("one");
// Should be caught be OnErrorResumeNextverify(stringObserver, never()).onError(any(Exception.class));
verify(stringObserver, never()).onNext("error");
verify(stringObserver, never()).onNext("two");
verify(stringObserver, never()).onNext("three");
// Resume outputverify(stringObserver, times(1)).onNext("II");
verify(stringObserver, times(1)).onNext("III");
verify(stringObserver, times(1)).onCompleted();
}
privateObservable<String> createSlowSequence(finalString[] seq) {
returnObservable.create(newFunc1<Observer<String>,Subscription>() {
publicSubscriptioncall(finalObserver<String> ob) {
newThread() {
/** Delay for a given time */publicvoidwaitFor(intms) {
try {
Thread.sleep(ms);
}
catch (InterruptedExceptione) {
}
}
/** Slowly emit a sequence */publicvoidrun() {
for (inti=0;i<seq.length;i++) {
waitFor(100);
ob.onNext(seq[i]);
}
ob.onCompleted();
}
}.start();
returnSubscriptions.empty();
}
});
}
There are two issues I see causing the problem, so two potential fixes.
MapObserver continues to emit onNext/onCompleted even after it has emitted onError. This pushes the problem downstream.
OnErrorResumeNext continues to propogate onNext/onCompleted even after it has subscribed the Observer(s) to the resume Observable.
This means that if the resume Observable is async OnErrorResumeNext will emit one/more onNext and potentially onCompleted from the source Observable unless the resume Observable completes.
It could also trigger multiple subscriptions if the MapObserver produced another onError.
A side note here is that the AtomicObserver fixes this issue if the resume Observable is sync (because it ignores the source Observable events after the resume Observable has completed). This effectively masks the problem in the OnErrorResumeNext unit-test. Perhaps the unit-tests should disable this behavior, or detect it via a plugin?
The text was updated successfully, but these errors were encountered:
This may be a problem with MapObserver or OnErrorResumeXXX and is probably related to #216
If the function returned by OnErrorResumeXXX returns an async Observable then there is some unpredictable behavior with operators (eg Map) that rely on the AtomicObserver to generate a valid event stream
I've created a UnitTest below to demonstrate the problem.
There are two issues I see causing the problem, so two potential fixes.
This means that if the resume Observable is async OnErrorResumeNext will emit one/more onNext and potentially onCompleted from the source Observable unless the resume Observable completes.
It could also trigger multiple subscriptions if the MapObserver produced another onError.
A side note here is that the AtomicObserver fixes this issue if the resume Observable is sync (because it ignores the source Observable events after the resume Observable has completed). This effectively masks the problem in the OnErrorResumeNext unit-test. Perhaps the unit-tests should disable this behavior, or detect it via a plugin?
The text was updated successfully, but these errors were encountered: