Skip to content

Commit

Permalink
Only retry for the specific thing raising EBUSY
Browse files Browse the repository at this point in the history
Fix: #187
  • Loading branch information
isaacs committed Jan 13, 2023
1 parent 5d5e87c commit 8ade1b6
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 7 deletions.
5 changes: 4 additions & 1 deletion src/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import fs from 'fs'

export type FsError = Error & { code?: string }
export type FsError = Error & {
code?: string
path?: string
}

// sync ones just take the sync version from node
export {
Expand Down
9 changes: 7 additions & 2 deletions src/retry-busy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const retryBusy = (fn: (path: string) => Promise<any>) => {
return await fn(path)
} catch (er) {
const fer = er as FsError
if (fer?.code && codes.has(fer.code)) {
if (fer?.path === path && fer?.code && codes.has(fer.code)) {
backoff = Math.ceil(backoff * rate)
total = backoff + total
if (total < mbo) {
Expand Down Expand Up @@ -57,7 +57,12 @@ export const retryBusySync = (fn: (path: string) => any) => {
return fn(path)
} catch (er) {
const fer = er as FsError
if (fer?.code && codes.has(fer.code) && retries < max) {
if (
fer?.path === path &&
fer?.code &&
codes.has(fer.code) &&
retries < max
) {
retries++
continue
}
Expand Down
8 changes: 4 additions & 4 deletions test/retry-busy.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ t.test('retry when known error code thrown', t => {
thrown = true
t.equal(calls, 0, 'first call')
calls++
throw Object.assign(new Error(code), { code })
throw Object.assign(new Error(code), { path: a, code })
} else {
t.equal(calls, 1, 'second call')
calls++
Expand Down Expand Up @@ -83,10 +83,10 @@ t.test('retry and eventually give up', t => {
t.equal(a, arg, 'got first argument')
t.equal(b, undefined, 'did not get another argument')
calls++
throw Object.assign(new Error(code), { code })
throw Object.assign(new Error(code), { path: a, code })
}
const rBS = retryBusySync(method)
t.throws(() => rBS(arg, opt), { code })
t.throws(() => rBS(arg, opt), { path: arg, code })
t.equal(calls, 3)
calls = 0
const rB = retryBusy(method)
Expand All @@ -101,7 +101,7 @@ t.test('throw unknown error gives up right away', async t => {
const method = (a, b) => {
t.equal(a, arg, 'got first argument')
t.equal(b, undefined, 'did not get another argument')
throw Object.assign(new Error('nope'), { code: 'nope' })
throw Object.assign(new Error('nope'), { path: a, code: 'nope' })
}
const rBS = retryBusySync(method)
t.throws(() => rBS(arg, opt), { code: 'nope' })
Expand Down

0 comments on commit 8ade1b6

Please sign in to comment.