Buckets:
| export interface RetryOptions { | |
| attempts?: number | |
| delay?: number | |
| factor?: number | |
| maxDelay?: number | |
| retryIf?: (error: unknown) => boolean | |
| } | |
| const TRANSIENT_MESSAGES = [ | |
| "load failed", | |
| "network connection was lost", | |
| "network request failed", | |
| "failed to fetch", | |
| "econnreset", | |
| "econnrefused", | |
| "etimedout", | |
| "socket hang up", | |
| ] | |
| function isTransientError(error: unknown): boolean { | |
| if (!error) return false | |
| // oxlint-disable-next-line no-base-to-string -- error is unknown, intentional coercion for message matching | |
| const message = String(error instanceof Error ? error.message : error).toLowerCase() | |
| return TRANSIENT_MESSAGES.some((m) => message.includes(m)) | |
| } | |
| export async function retry<T>(fn: () => Promise<T>, options: RetryOptions = {}): Promise<T> { | |
| const { attempts = 3, delay = 500, factor = 2, maxDelay = 10000, retryIf = isTransientError } = options | |
| let lastError: unknown | |
| for (let attempt = 0; attempt < attempts; attempt++) { | |
| try { | |
| return await fn() | |
| } catch (error) { | |
| lastError = error | |
| if (attempt === attempts - 1 || !retryIf(error)) throw error | |
| const wait = Math.min(delay * Math.pow(factor, attempt), maxDelay) | |
| await new Promise((resolve) => setTimeout(resolve, wait)) | |
| } | |
| } | |
| throw lastError | |
| } | |
Xet Storage Details
- Size:
- 1.29 kB
- Xet hash:
- b47d2058ddbe9fd9b2b3cdb8b499590254f78349a2752fe1f94137aff8ec19d8
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.