diff --git a/README.md b/README.md index 921a108..c7a1049 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,9 @@ export interface RetryConfig { // maximal backoff in ms (default: 5 * 60 * 1000) maxBackOff?: number; + + // allows to abort retrying for certain errors (default: () => true) + retryIf: (error: any) => boolean } ``` diff --git a/src/retry-promise.ts b/src/retry-promise.ts index 75ab9eb..984ac86 100644 --- a/src/retry-promise.ts +++ b/src/retry-promise.ts @@ -23,6 +23,9 @@ export interface RetryConfig { // maximal backoff in ms (default: 5 * 60 * 1000) maxBackOff: number; + + // allows to abort retrying for certain errors + retryIf: (error: any) => boolean } const fixedBackoff = (attempt: number, delay: number) => delay; @@ -37,6 +40,7 @@ export const defaultRetryConfig: RetryConfig = { retries: 10, timeout: 60 * 1000, until: () => true, + retryIf: () => true }; export async function wait(ms: number): Promise { @@ -98,6 +102,10 @@ async function _retry(f: () => Promise, config: RetryConfig, done: () = } config.logger("Until condition not met by " + result); } catch (error) { + if (!config.retryIf(error)) { + throw error; + } + if (error.name === NotRetryableError.name) { throw new RetryError( `Met not retryable error. Last error: ${error}`, diff --git a/test/retry-promise.test.ts b/test/retry-promise.test.ts index 5767afd..988f1ef 100644 --- a/test/retry-promise.test.ts +++ b/test/retry-promise.test.ts @@ -153,6 +153,31 @@ describe("Retry Promise", () => { }, {retries: 1})) .to.be.eventually.rejected.with.property("lastError", error); }); + + it("should stop retrying if retryIf is false", async () => { + const failer = new Failer(1); + + const result = retry(() => failer.run(), {retryIf: () => false}); + + await expect(result).to.eventually.be.rejected + expect(failer.calls).to.eq(1); + }); + + it("should provide error to retryIf function", async () => { + const error = Error("fail") + let passedError: Error | undefined; + + const result = retry(() => { + throw error + }, { + retryIf: e => { + passedError = e + return false; + } + }); + await expect(result).to.eventually.be.rejected; + expect(passedError).to.eq(error); + }); }); class Failer {