Add realtime watcher+SSE transport with tests and lock-retry read path
This commit is contained in:
parent
cc616c1543
commit
3f2ae384f5
15 changed files with 727 additions and 75 deletions
41
src/lib/read-text-retry.ts
Normal file
41
src/lib/read-text-retry.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import fs from 'node:fs/promises';
|
||||
|
||||
const DEFAULT_RETRY_CODES = new Set(['EBUSY', 'EPERM']);
|
||||
|
||||
export interface ReadTextRetryOptions {
|
||||
retries?: number;
|
||||
delayMs?: number;
|
||||
retryCodes?: Set<string>;
|
||||
}
|
||||
|
||||
function sleep(delayMs: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, delayMs));
|
||||
}
|
||||
|
||||
function shouldRetry(error: unknown, retryCodes: Set<string>): boolean {
|
||||
const code = (error as NodeJS.ErrnoException | undefined)?.code;
|
||||
return typeof code === 'string' && retryCodes.has(code);
|
||||
}
|
||||
|
||||
export async function readTextFileWithRetry(
|
||||
filePath: string,
|
||||
options: ReadTextRetryOptions = {},
|
||||
): Promise<string> {
|
||||
const retries = options.retries ?? 2;
|
||||
const delayMs = options.delayMs ?? 40;
|
||||
const retryCodes = options.retryCodes ?? DEFAULT_RETRY_CODES;
|
||||
|
||||
let attempt = 0;
|
||||
while (true) {
|
||||
try {
|
||||
return await fs.readFile(filePath, 'utf8');
|
||||
} catch (error) {
|
||||
if (attempt >= retries || !shouldRetry(error, retryCodes)) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
attempt += 1;
|
||||
await sleep(delayMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue