@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
JavaScript
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