-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Proposal: Changes to retryWhen #1413
Comments
I took a look at retryWhen.ts, thought about your suggestions, and I think it's a reasonable breaking change. |
I just spoke with @abersnaze here at Netflix, and I think there's a way to do this without a breaking change. Basically, the idea is to add an optional second parameter that fires for each source.retryWhen(errs => errs.switchMap((_, i) => Observable.timer(2**i)), (value, sub) => sub.unsubscribe()); Another option would be a second argument that was the same idea, but you just returned a boolean of whether or not to end the subscription. EDIT: To clarifyA boolean variant instead, where source.retryWhen(errs => errs.switchMap((_, i) => Observable.timer(2**i)), (value) => true); An async variant of the same, where a source.retryWhen(errs => errs.switchMap((_, i) => Observable.timer(2**i)), (value) => Observable.of('whatever')); Or another, where you get a stream of all nexted values, and return a stream of notifications to retry the retry notifier (probably too confusing): source.retryWhen(errs => errs.switchMap((_, i) => Observable.timer(2**i)), (values) => values.switchMap(() => timer(100))); |
Also, @stealthcode (from Netflix) had some thoughts about a different design (as a new operator). His concern with tearing down the inner subscription and starting it back up was based on the principle that that's an additional teardown and setup that you might not need. He wanted to try to keep the inner subscription .. so it would look like this: retryWhenWithNext(notifierFactory: (errorsOrNexts: Observable<any>) => Observable<any>) The idea here is that each call to next or error would come through the observable passed to the notifierFactory.
Given that type-checking in JavaScript isn't a thing, I'm not sure how this approach would work for us, so perhaps in our case it would be better to have a stream of repeatWhenNotified(notifierFactory: (notifications: Observable<Notification<T>>) => Observable<any>) It's another design, and it's interesting, because it would actually allow for retries on async actions after errors, completions or nexted values. |
@mattpodwysocki I'd really like your thoughts here, there's a lot in this thread. |
I'm of the mind, that even if we implement a |
I've edited my comment above to clarify the options presented there. |
+1 |
I think this issue still has merit... leaving it for now. |
@benlesh I'm having exactly this issue while implementing a polling library based on RxJS. Is there any current, even dirty and extremely hacky, way to workaround this issue? EDIT: I think I've solved it using a counter to keep track of let allErrorsCount = 0;
let lastRecoverCount = 0;
Observable.interval(1000)
.switchMap(() => request$)
.retryWhen(errors$ => {
return errors$.scan((errorCount, err) => errorCount + 1, 0).switchMap(errorCount => {
allErrorsCount = errorCount;
const consecutiveErrorsCount = allErrorsCount - lastRecoverCount;
const esponentialDelay = Math.pow(2, consecutiveErrorsCount) * 1000;
return Observable.timer(esponentialDelay, null, scheduler);
});
})
.do(() => {
// Update the counter after success recover
lastRecoverCount = allErrorsCount;
}); What do you think? About the proposal, if I can give an opinion, I'd prefer this option:
That's because you can:
This operator also would be very nice IMO and would respect the 3 points I've mentioned, but since it's a new operator there should be other use cases for it |
Fixes RxJS issue ReactiveX/rxjs#1413
This is pretty old, and there hasn't been much appetite to change it. However, we did at a "reset" to the |
These would be breaking changes, but here goes:
Problem
Often with retryWhen there is a desire to reset some "state" of your retries when the stream your retrying starts receiving values successfully again. For example, in a network retry scenario where you want to exponentially step back from the first failure. Once you get a value over that network observable, you want to reset your exponential step back to the first level again, because things are going well now.
Current Solution
The current solution involves adding some peice of mutable state and altering it via side-effects:
Proposed Change (and solution)
I propose a change that says the first successful value to "next" through the retryWhen subscriber causes the retry nofication subscription to unsubscribe, which will "reset" the state of any observable inside of there.
The behavior:
result
source
and passes through successful values and completionserror
from source, theerror
is pumped into a Subject, and the notifier function passed toretryWhen
is called with an Observable created from that Subject.next
from the notifier, thesource
subscription is retried.a. On first successful message from
source
, unsubscribe fromnotifier
, then goto 3.error
from the notifier, an error is sent down the chain to the result.complete
from the notifier, the completion is sent down the chain to the result.The text was updated successfully, but these errors were encountered: