Spaces:
Sleeping
Sleeping
Download src/utils/retry.ts from relv-dev/relv-space6: direct link, hf CLI and curl.
- Browser
- Download file 1.41 kB
-
https://huggingface.co/spaces/relv-dev/relv-space6/resolve/main/src/utils/retry.ts
- Command line
-
hf download hf://spaces/relv-dev/relv-space6/src/utils/retry.ts
-
curl -L -o retry.ts https://huggingface.co/spaces/relv-dev/relv-space6/resolve/main/src/utils/retry.ts
1.41 kB
| import { logger } from './logger'; | |
| interface RetryOptions { | |
| maxAttempts: number; | |
| baseDelayMs?: number; | |
| maxDelayMs?: number; | |
| retryIf?: (error: unknown) => boolean; | |
| label?: string; | |
| } | |
| /** | |
| * Retry a function with exponential backoff. | |
| * Returns the result on success or throws after all attempts fail. | |
| */ | |
| export async function retry<T>( | |
| fn: () => Promise<T>, | |
| options: RetryOptions | |
| ): Promise<T> { | |
| const { | |
| maxAttempts, | |
| baseDelayMs = 1000, | |
| maxDelayMs = 30000, | |
| retryIf, | |
| label = 'operation', | |
| } = options; | |
| let lastError: unknown; | |
| for (let attempt = 1; attempt <= maxAttempts; attempt++) { | |
| try { | |
| return await fn(); | |
| } catch (error) { | |
| lastError = error; | |
| if (retryIf && !retryIf(error)) { | |
| throw error; | |
| } | |
| if (attempt === maxAttempts) { | |
| break; | |
| } | |
| const delay = Math.min(baseDelayMs * Math.pow(2, attempt - 1), maxDelayMs); | |
| const jitter = delay * (0.5 + Math.random() * 0.5); | |
| logger.warn(`${label} attempt ${attempt}/${maxAttempts} failed, retrying in ${Math.round(jitter)}ms`, { | |
| error: error instanceof Error ? error.message : String(error), | |
| attempt, | |
| maxAttempts, | |
| }); | |
| await sleep(jitter); | |
| } | |
| } | |
| throw lastError; | |
| } | |
| /** Promise-based sleep */ | |
| export function sleep(ms: number): Promise<void> { | |
| return new Promise((resolve) => setTimeout(resolve, ms)); | |
| } | |