Skip to content

Commit

Permalink
feat: added onRetry option for retry fn
Browse files Browse the repository at this point in the history
  • Loading branch information
gperdomor committed Aug 30, 2024
1 parent 5f257bf commit d8ce877
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 2 deletions.
8 changes: 8 additions & 0 deletions docs/async/retry.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ The `times` option defaults to `3`. The `delay` option (defaults to null) can sp

The `backoff` option is like delay but uses a function to sleep -- makes for easy exponential backoff.

The `onRetry` option is a Function that is invoked after a new retry is performed. It's passed the Error that triggered it as a parameter and the attempt number.

```ts
import * as _ from 'radashi'

Expand All @@ -20,4 +22,10 @@ await _.retry({ times: 2, delay: 1000 }, api.users.list)

// exponential backoff
await _.retry({ backoff: i => 10 ** i }, api.users.list)

// onRetry usage
await _.retry(
{ onRetry: (err, i) => console.log(`Trying again... Attempt: ${i}`) },
api.users.list,
)
```
5 changes: 5 additions & 0 deletions src/async/retry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { sleep, tryit } from 'radashi'
export type RetryOptions = {
times?: number
delay?: number | null
onRetry?: (err: Error, num: number) => void
backoff?: (count: number) => number
}

Expand All @@ -24,6 +25,7 @@ export async function retry<TResponse>(
const times = options?.times ?? 3
const delay = options?.delay
const backoff = options?.backoff ?? null
const onRetry = options?.onRetry ?? null
let i = 0
while (true) {
const [err, result] = (await tryit(func)((err: any) => {
Expand All @@ -38,6 +40,9 @@ export async function retry<TResponse>(
if (++i >= times) {
throw err
}
if (onRetry) {
onRetry(err, i)
}
if (delay) {
await sleep(delay)
}
Expand Down
19 changes: 17 additions & 2 deletions tests/async/retry.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// cSpell:ignore backoffs

import * as _ from 'radashi'
import type { RetryOptions } from 'radashi'
import * as _ from 'radashi'

const cast = <T = RetryOptions>(value: any): T => value

Expand All @@ -16,9 +16,11 @@ describe('retry', () => {
expect(result).toBe('hello')
})
test('simple + quick + happy path', async () => {
const result = await _.retry(cast(null), async () => {
const onRetry = vi.fn()
const result = await _.retry({ onRetry }, async () => {
return 'hello'
})
expect(onRetry).not.toBeCalled()
expect(result).toBe('hello')
})
test('retries on failure', async () => {
Expand All @@ -32,6 +34,19 @@ describe('retry', () => {
})
expect(result).toBe('hello')
})
test('call onRetry function on retries', async () => {
let failedOnce = false
const onRetry = vi.fn()
const result = await _.retry({ onRetry }, async _bail => {
if (!failedOnce) {
failedOnce = true
throw 'Failing for test'
}
return 'hello'
})
expect(onRetry).toBeCalledWith('Failing for test', 1)
expect(result).toBe('hello')
})
test('quits on bail', async () => {
try {
await _.retry({}, async bail => {
Expand Down

0 comments on commit d8ce877

Please sign in to comment.