1.x: implement OperatorDoOnEmpty, with Observable.doOnEmpty() operator#3624
1.x: implement OperatorDoOnEmpty, with Observable.doOnEmpty() operator#3624thomasnield wants to merge 10 commits into
Conversation
There was a problem hiding this comment.
Should this call get a try catch and Exceptions.throwOrReport called? If so, I'll put in a PR for OperatorDoAfterTerminate as well.
There was a problem hiding this comment.
I might have misunderstood Exceptions.throwOrReport. Does "reporting" pass it up the chain via onError() and throw simply throws an exception without passing it?
|
I saw there was an |
|
Okay two questions:
|
There was a problem hiding this comment.
Please make sure the imports stay with * because it is a source of merge conflict otherwise.
use a
use a |
|
@akarnokd Done. The unsubscription test made sense to me. Not too familiar with the |
|
@akarnokd Might help if I actually used the operator in question. One second... |
|
Okay unit tests are complete. |
|
Hey Thomas, for your convenience what you normally do is make a branch of 1.x say |
|
Okay, thanks @davidmoten. I'll branch the feature separately next time. |
There was a problem hiding this comment.
Should use assertTrue everywhere in the unit tests rather than assert to ensure the assertions are run regardless of runtime flags.
|
Dang it IDEA, sorry my habits have caused Observable to have irrelevant changes. One moment. |
|
There are too many, probably irrelevant, changes in In addition, your reuse of Observable<Integer> o = Observable.defer(
() -> Observable.range(1, counter.getAndIncrement() % 2))
.doOnEmpty(() -> System.out.println("Empty!"));
o.subscribe(System.out::println);
o.subscribe(System.out::println);
o.subscribe(System.out::println);
o.subscribe(System.out::println);
o.subscribe(System.out::println);This should print 3 |
|
That seems like a deliberate side effect almost... so what would the expected behavior be? Because I don't really see how it is much different from |
|
Oh shoot, I think I see what you are saying. I was sharing state between the subscriptions. Let me figure out how to do this... |
|
Alright, I started over on the implementation and placed that |
| try { | ||
| onEmpty.call(); | ||
| } catch (Exception e) { | ||
| Exceptions.throwIfFatal(e); |
There was a problem hiding this comment.
If a non-fatal error occurs in onEmpty.call() then at the moment it would complete normally. Moreover you should catch for Throwables not just Exceptions.
This should be
catch (Throwable e) {
Exceptions.throwOrReport(e, this);
return;
}Tests for these scenarios would be nice too.
There was a problem hiding this comment.
Okay I will put all these on my list today.
|
Question. Why is it the policy that EDIT Let me rephrase that. Should exceptions in the side-effect function be emitted to the child's |
| try { | ||
| onEmpty.call(); | ||
| } catch (Throwable e) { | ||
| Exceptions.throwIfFatal(e); |
There was a problem hiding this comment.
Is this the proper way to handle an error occurring in the side effect function onEmpty?
There was a problem hiding this comment.
No Thomas, I've given you the way to do it in my previous comment (and the method used calls onError).
There was a problem hiding this comment.
Okay I thought I missed something in my notes. I'll fix it.
There was a problem hiding this comment.
Exceptions.throwOrReport(), that's what I was looking for (and I think that is what you said). Thanks for your patience, I'm learning a lot.
| onEmpty.call(); | ||
| } catch (Throwable e) { | ||
| Exceptions.throwOrReport(e,this); | ||
| } |
There was a problem hiding this comment.
add return; after call to Exceptions.throwOrReport. Thomas I suggest you read the comments on the github site because it seems like you are reacting to truncated comments (perhaps email notifications).
There was a problem hiding this comment.
You're right I was reading email notifications.
| } | ||
| child.onCompleted(); | ||
| done = true; | ||
| } |
There was a problem hiding this comment.
Because onEmpty.call could take a non-trivial time to complete I would normally put in a isUnsubscribed check before calling child.onCompleted(). I'd suggest this rejig:
@Override
public void onCompleted() {
if (done) {
return;
}
if (isEmpty) {
try {
onEmpty.call();
} catch (Throwable e) {
Exceptions.throwOrReport(e,this);
return;
}
if (!isUnsubscribed()) {
child.onCompleted();
}
} else {
child.onCompleted();
}
done = true;
}|
Okay it's done, @davidmoten. Please let me know if I missed anything else... |
|
It looks like a test failed. I don't think it has to do with this feature, but I'll confirm tomorrow after I update my fork and see if that rids it. |
|
I think this operator was about done so I chucked it into https://github.com/davidmoten/rxjava-extras. That ok with you @thomasnield? |
|
@davidmoten That sounds great! I'm glad you did, thanks! |
See #3621