Skip to content

Commit c2db624

Browse files
committed
feat: Add EMFILE/ENFILE retry
1 parent 9a6b62d commit c2db624

File tree

5 files changed

+317
-14
lines changed

5 files changed

+317
-14
lines changed

packages/deno/deno.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"imports": {
33
"fsx-core": "../core/src/fsx.js",
4-
"fsx-types": "../types/src/fsx-types.ts"
4+
"fsx-types": "../types/src/fsx-types.ts",
5+
"@humanwhocodes/retry": "npm:@humanwhocodes/retry@latest"
56
}
67
}

packages/deno/deno.lock

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/deno/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@
3636
},
3737
"homepage": "https://github.com/humanwhocodes/fsx#readme",
3838
"devDependencies": {
39-
"typescript": "^5.2.2",
40-
"@types/node": "^20.9.4"
39+
"@types/node": "^20.9.4",
40+
"typescript": "^5.2.2"
41+
},
42+
"dependencies": {
43+
"@humanwhocodes/retry": "^0.1.2"
4144
}
4245
}

packages/deno/src/deno-fsx.js

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,15 @@
1515
//-----------------------------------------------------------------------------
1616

1717
import { Fsx } from "fsx-core";
18+
import { Retrier } from "@humanwhocodes/retry";
1819
import path from "node:path";
1920

21+
//-----------------------------------------------------------------------------
22+
// Constants
23+
//-----------------------------------------------------------------------------
24+
25+
const RETRY_ERROR_CODES = new Set(["ENFILE", "EMFILE"]);
26+
2027
//-----------------------------------------------------------------------------
2128
// Exports
2229
//-----------------------------------------------------------------------------
@@ -32,13 +39,20 @@ export class DenoFsxImpl {
3239
*/
3340
#deno;
3441

42+
/**
43+
* The retryer object used for retrying operations.
44+
* @type {Retrier}
45+
*/
46+
#retrier;
47+
3548
/**
3649
* Creates a new instance.
3750
* @param {object} [options] The options for the instance.
3851
* @param {Deno} [options.deno] The Deno object to use.
3952
*/
4053
constructor({ deno = Deno } = {}) {
4154
this.#deno = deno;
55+
this.#retrier = new Retrier(error => RETRY_ERROR_CODES.has(error.code));
4256
}
4357

4458
/**
@@ -53,13 +67,15 @@ export class DenoFsxImpl {
5367
* @throws {RangeError} If the file path is not readable.
5468
*/
5569
text(filePath) {
56-
return this.#deno.readTextFile(filePath).catch(error => {
57-
if (error.code === "ENOENT") {
58-
return undefined;
59-
} else {
70+
return this.#retrier
71+
.retry(() => this.#deno.readTextFile(filePath))
72+
.catch(error => {
73+
if (error.code === "ENOENT") {
74+
return undefined;
75+
}
76+
6077
throw error;
61-
}
62-
});
78+
});
6379
}
6480

6581
/**
@@ -86,15 +102,15 @@ export class DenoFsxImpl {
86102
* @throws {TypeError} If the file path is not a string.
87103
*/
88104
arrayBuffer(filePath) {
89-
return this.#deno
90-
.readFile(filePath)
105+
return this.#retrier
106+
.retry(() => this.#deno.readFile(filePath))
91107
.then(bytes => bytes.buffer)
92108
.catch(error => {
93109
if (error.code === "ENOENT") {
94110
return undefined;
95-
} else {
96-
throw error;
97111
}
112+
113+
throw error;
98114
});
99115
}
100116

@@ -125,7 +141,7 @@ export class DenoFsxImpl {
125141
},
126142
);
127143

128-
return op().catch(error => {
144+
return this.#retrier.retry(op).catch(error => {
129145
if (error.code === "ENOENT") {
130146
return this.#deno
131147
.mkdir(path.dirname(filePath), { recursive: true })

0 commit comments

Comments
 (0)