UNPKG

@pulzar/core

Version:

Next-generation Node.js framework for ultra-fast web applications with zero-reflection DI, GraphQL, WebSockets, events, and edge runtime support

88 lines 3.06 kB
export class RetryError extends Error { attempts; lastError; constructor(message, attempts, lastError) { super(message); this.attempts = attempts; this.lastError = lastError; this.name = "RetryError"; } } export async function retry(fn, options = {}) { const { maxAttempts = 3, baseDelay = 1000, maxDelay = 30000, backoffMultiplier = 2, jitter = true, retryCondition = () => true, } = options; const startTime = Date.now(); let lastError; for (let attempt = 1; attempt <= maxAttempts; attempt++) { try { const data = await fn(); return { success: true, data, attempts: attempt, totalTime: Date.now() - startTime, }; } catch (error) { lastError = error; // Check if we should retry if (attempt === maxAttempts || !retryCondition(error)) { return { success: false, error, attempts: attempt, totalTime: Date.now() - startTime, }; } // Calculate delay with exponential backoff const delay = Math.min(baseDelay * Math.pow(backoffMultiplier, attempt - 1), maxDelay); // Add jitter if enabled const finalDelay = jitter ? delay * (0.5 + Math.random() * 0.5) : delay; // Wait before next attempt await sleep(finalDelay); } } throw new RetryError(`Failed after ${maxAttempts} attempts`, maxAttempts, lastError); } export function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } // Utility for creating retryable functions export function withRetry(fn, options = {}) { return ((...args) => retry(() => fn(...args), options)); } // Predefined retry conditions export const retryConditions = { // Retry on any error always: () => true, // Retry only on network errors networkErrors: (error) => { const networkErrorCodes = [ "ECONNRESET", "ECONNREFUSED", "ENOTFOUND", "ETIMEDOUT", ]; return networkErrorCodes.includes(error.code); }, // Retry on 5xx server errors serverErrors: (error) => { return error.status >= 500 && error.status < 600; }, // Retry on rate limit errors rateLimitErrors: (error) => { return error.status === 429; }, // Retry on timeout errors timeoutErrors: (error) => { return error.code === "ETIMEDOUT" || error.message?.includes("timeout"); }, }; // Exponential backoff calculator export function calculateBackoff(attempt, baseDelay = 1000, maxDelay = 30000, backoffMultiplier = 2) { return Math.min(baseDelay * Math.pow(backoffMultiplier, attempt - 1), maxDelay); } // Jitter calculator export function addJitter(delay, factor = 0.5) { return delay * (1 - factor + Math.random() * factor); } //# sourceMappingURL=retry.js.map