( fn: () => Promise<T>, attempts = 3, baseMs = 200, )
| 172 | } |
| 173 | |
| 174 | async function withTransientRetry<T>( |
| 175 | fn: () => Promise<T>, |
| 176 | attempts = 3, |
| 177 | baseMs = 200, |
| 178 | ): Promise<T> { |
| 179 | let lastError: unknown = new Error('withTransientRetry did not execute') |
| 180 | for (let attempt = 1; attempt <= attempts; attempt += 1) { |
| 181 | try { |
| 182 | return await fn() |
| 183 | } catch (error) { |
| 184 | lastError = error |
| 185 | if (attempt >= attempts || !isTransientError(error)) { |
| 186 | break |
| 187 | } |
| 188 | logForDebugging( |
| 189 | `Transient retry ${attempt}/${attempts}: ${error instanceof Error ? error.message : String(error)}`, |
| 190 | ) |
| 191 | const jitter = Math.random() * baseMs |
| 192 | await new Promise(resolve => setTimeout(resolve, baseMs * 2 ** (attempt - 1) + jitter)) |
| 193 | } |
| 194 | } |
| 195 | throw lastError |
| 196 | } |
| 197 | |
| 198 | export async function registerOauthCallbackRelay(params: { |
| 199 | relayId: string |
no test coverage detected