* Execute a file operation with throttling and retry logic
(operation: () => Promise<T>, operationName: string)
| 115 | * Execute a file operation with throttling and retry logic |
| 116 | */ |
| 117 | async function executeWithRetry<T>(operation: () => Promise<T>, operationName: string): Promise<T> { |
| 118 | return fsLimit(async () => { |
| 119 | let lastError: unknown; |
| 120 | |
| 121 | for (let attempt = 0; attempt <= config.maxRetries; attempt++) { |
| 122 | try { |
| 123 | return await operation(); |
| 124 | } catch (error) { |
| 125 | lastError = error; |
| 126 | |
| 127 | if (isFileDescriptorError(error) && attempt < config.maxRetries) { |
| 128 | const delay = calculateDelay(attempt); |
| 129 | console.warn( |
| 130 | `[SecureFS] ${operationName}: File descriptor error (attempt ${attempt + 1}/${config.maxRetries + 1}), retrying in ${delay}ms` |
| 131 | ); |
| 132 | await sleep(delay); |
| 133 | continue; |
| 134 | } |
| 135 | |
| 136 | throw error; |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | throw lastError; |
| 141 | }); |
| 142 | } |
| 143 | |
| 144 | /** |
| 145 | * Wrapper around fs.access that validates path first |
no test coverage detected