Skip to content

Instantly share code, notes, and snippets.

@ericzakariasson
Created September 15, 2021 07:43
Show Gist options
  • Save ericzakariasson/20b9adebb50f2fde49a703254941ed1f to your computer and use it in GitHub Desktop.
Save ericzakariasson/20b9adebb50f2fde49a703254941ed1f to your computer and use it in GitHub Desktop.
describe("withRetry", () => {
it("should retry if when condition is true", async () => {
const fn = jest
.fn()
.mockImplementationOnce(() => {
throw new Error("Should throw");
})
.mockImplementationOnce(() => 1);
let retryCount = 0;
const result = await withRetry<number>(fn, {
when: (error) => error instanceof Error,
do: () => retryCount++,
});
expect(result).toBe(1);
expect(retryCount).toBe(1);
});
it("should throw if retry limit is crossed", async () => {
const fn = jest.fn().mockImplementation(() => {
throw new Error("Will throw");
});
expect(() =>
withRetry<number>(fn, {
when: (error) => error instanceof Error,
})
).rejects.toThrowError("Will throw");
});
});
interface WithRetryOptions {
when: (error: unknown) => boolean;
do?: () => unknown | Promise<unknown>;
}
export async function withRetry<T>(
fn: () => Promise<T>,
options: WithRetryOptions,
retries = 1
): Promise<T> {
try {
return await fn();
} catch (error) {
if (options.when(error) && retries > 0) {
await options.do?.();
return withRetry(fn, options, retries - 1);
}
throw error;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment