Files
makelore/electron/opencode/filesystem-retry.ts
2026-07-29 17:22:35 +08:00

41 lines
1.1 KiB
TypeScript

export interface FilesystemRetryOptions {
retryDelaysMs?: readonly number[];
wait?: (delayMs: number) => void;
}
const DEFAULT_RETRY_DELAYS_MS = [100, 300, 900] as const;
const TRANSIENT_FILESYSTEM_ERROR_CODES = new Set([
'EIO',
'EPERM',
'EBUSY',
'EACCES',
]);
function waitSynchronously(delayMs: number): void {
const signal = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
Atomics.wait(signal, 0, 0, delayMs);
}
export function retryTransientFilesystemOperation<T>(
operation: () => T,
options: FilesystemRetryOptions = {},
): T {
const retryDelaysMs = options.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS;
const wait = options.wait ?? waitSynchronously;
for (let attempt = 0; ; attempt += 1) {
try {
return operation();
} catch (error) {
const code = error && typeof error === 'object' && 'code' in error
? String(error.code)
: '';
const delayMs = retryDelaysMs[attempt];
if (!TRANSIENT_FILESYSTEM_ERROR_CODES.has(code) || delayMs === undefined) {
throw error;
}
wait(delayMs);
}
}
}