Skip to content

Commit 54dfd76

Browse files
committed
fix: retry transient flagged storage reads
(cherry picked from commit 1a5eca3)
1 parent 1e8c9b0 commit 54dfd76

File tree

2 files changed

+79
-530
lines changed

2 files changed

+79
-530
lines changed
Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,41 @@
11
import type { FlaggedAccountStorageV1 } from "../storage.js";
2+
import { sleep } from "../utils.js";
3+
4+
const RETRYABLE_READ_CODES = new Set(["EBUSY", "EPERM", "EAGAIN"]);
5+
6+
function isRetryableReadError(error: unknown): boolean {
7+
const code = (error as NodeJS.ErrnoException | undefined)?.code;
8+
return typeof code === "string" && RETRYABLE_READ_CODES.has(code);
9+
}
10+
11+
async function readFileWithRetry(
12+
path: string,
13+
deps: {
14+
readFile: typeof import("node:fs").promises.readFile;
15+
sleep?: (ms: number) => Promise<void>;
16+
},
17+
): Promise<string> {
18+
for (let attempt = 0; ; attempt += 1) {
19+
try {
20+
return await deps.readFile(path, "utf-8");
21+
} catch (error) {
22+
if (!isRetryableReadError(error) || attempt >= 3) {
23+
throw error;
24+
}
25+
await (deps.sleep ?? sleep)(10 * 2 ** attempt);
26+
}
27+
}
28+
}
229

330
export async function loadFlaggedAccountsFromFile(
431
path: string,
532
deps: {
633
readFile: typeof import("node:fs").promises.readFile;
734
normalizeFlaggedStorage: (data: unknown) => FlaggedAccountStorageV1;
35+
sleep?: (ms: number) => Promise<void>;
836
},
937
): Promise<FlaggedAccountStorageV1> {
10-
const content = await deps.readFile(path, "utf-8");
38+
const content = await readFileWithRetry(path, deps);
1139
const data = JSON.parse(content) as unknown;
1240
return deps.normalizeFlaggedStorage(data);
1341
}

0 commit comments

Comments
 (0)