-
Notifications
You must be signed in to change notification settings - Fork 150
Rewrite errors observable #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rewrite errors observable #73
Conversation
We were directly looking at `inputs`, this could cause unpredictable execution order under certain conditions, and trigger a `notEnabledError` before execution begins.
…ause out-of-order erroring
|
Regarding a repro and possible test case for this: In our case, we were doing the following, all in the same method:
|
| let subject = ReplaySubject<Element>.createUnbounded() | ||
|
|
||
| let work = executionObservables | ||
| .map { $0.catchError { throw ActionError.underlyingError($0) } } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is throw ActionError.underlyingError($0) necessary?
The error seems to appear in errors subject too.
If that is true, catchError { _ in Observable.empty() } is more suitable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you look at the previous code, it was acting exactly like my code -- propagate errors to the execution observable returned by the execute() function, both for errors produced by the execution, and for the notEnabled error. I kept the same behaviour.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got it 👍
| return Observable.of(workFactory(input).shareReplay(1)) | ||
| return Observable.of(workFactory(input) | ||
| .do(onError: { errorsSubject.onNext(.underlyingError($0)) }) | ||
| .shareReplay(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Introducing variable for the execution observable makes this part more readable.
let execution = workFactory(input)
.do(onError: { errorsSubject.onNext(.underlyingError($0)) })
.shareReplay(1)
return Observable.of(execution)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how this makes the code more readable. Actually I think it makes it less readable (but that's nitpicking too)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Let's leave it as it is.
|
I'll try to get this released tomorrow, thanks again 👍 |
|
Okay, all released for CocoaPods and Carthage! |
|
Thanks, Ash! 👏 |
This PR rewrites both the creation of Action's
errorobservable inside the Action itself and restructures error handling in theexecutefunction.The motivation is to try and fix #63. The only plausible reason that could explain this issue is that the
notEnabledErrorobservable previously created was derived frominputs. SinceexecutionObservable(the root observable for all other work inside action) was derived frominputstoo, one couldn't guarantee the order of processing oninputupdate, depending on who subscribed to what and in what order.To fix the issue, I decided to have a single point of contact with
inputs, and derive everything from it. This led to some not-perfectly-Rx-y code where I push errors to an internal subject using side effects, but it really is less important than getting Action to perform right in all circumstances.I still have to find a way to reproduce issue #63, waiting on @tomburns to confirm whether this change fixes his issues.