Skip to content

Instantly share code, notes, and snippets.

@zakhenry
Created December 11, 2017 21:23
Show Gist options
  • Save zakhenry/764de6694751e3fdcd7aa61dffaa9aeb to your computer and use it in GitHub Desktop.
Save zakhenry/764de6694751e3fdcd7aa61dffaa9aeb to your computer and use it in GitHub Desktop.
RxJS typescript lettable retry exponential backoff function
import { Observable } from 'rxjs/Observable';
import { retryExponentialBackoff } from './exponential-backoff';
let attemptCount = 0;
Observable.create(function (observer) {
console.log('observable tried', attemptCount++);
observer.error(new Error('fail'));
})
.let(retryExponentialBackoff({
maxRetries: 3,
}));
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/timer';
import 'rxjs/add/operator/scan';
import 'rxjs/add/operator/let';
import 'rxjs/add/operator/retryWhen';
interface ExponentialBackoffHandlerConfig<E> {
maxRetries?: number,
startingInterval?: number,
exponent?: number,
fatalErrorMatcher?: (error: E) => never | void,
finalErrorHandler?: (error: E) => never
}
type BackoffResponse<T> = (observableThatMightFail: Observable<T>) => Observable<T>;
export function retryExponentialBackoff<T, E>({
maxRetries = 10,
startingInterval = 100,
exponent = 2,
fatalErrorMatcher = undefined,
finalErrorHandler = e => { throw e },
}: ExponentialBackoffHandlerConfig<E>): BackoffResponse<T> {
return (observableThatMightFail: Observable<T>) => {
return observableThatMightFail
.retryWhen((errors: Observable<E>) => {
return errors.scan((errCount: number, err: E) => {
if (fatalErrorMatcher) {
fatalErrorMatcher(err);
}
if (errCount >= maxRetries) {
finalErrorHandler(err);
}
return errCount + 1;
}, 0)
.switchMap((retryCount) => {
return Observable.timer(startingInterval * (retryCount ** exponent));
});
});
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment