UNPKG

@sailboat-computer/event-bus

Version:

Standardized event bus for sailboat computer v3 with resilience features and offline capabilities

99 lines 3.16 kB
"use strict"; /** * Retry utilities for the event bus */ Object.defineProperty(exports, "__esModule", { value: true }); exports.retry = exports.DEFAULT_RETRY_OPTIONS = void 0; const logger_1 = require("./logger"); /** * Default retry options */ exports.DEFAULT_RETRY_OPTIONS = { maxRetries: 3, baseDelay: 1000, maxDelay: 30000, exponential: true, jitter: 0.2, onRetry: (error, attempt, delay) => { logger_1.logger.warn(`Retry attempt ${attempt} after ${delay}ms due to error: ${error.message}`); } }; /** * Retry a function with exponential backoff * * @param fn - Function to retry * @param options - Retry options * @returns Promise that resolves with the function result or rejects with the last error */ async function retry(fn, options = {}) { const retryOptions = { ...exports.DEFAULT_RETRY_OPTIONS, ...options }; let lastError; for (let attempt = 0; attempt <= retryOptions.maxRetries; attempt++) { try { // First attempt is not a retry if (attempt === 0) { return await fn(); } // Calculate delay with exponential backoff and jitter const delay = calculateDelay(attempt, retryOptions); // Call onRetry callback if provided if (retryOptions.onRetry && lastError) { retryOptions.onRetry(lastError, attempt, delay); } // Wait for the calculated delay await sleep(delay); // Try again return await fn(); } catch (error) { lastError = error instanceof Error ? error : new Error(String(error)); // Check if we've reached the maximum number of retries if (attempt >= retryOptions.maxRetries) { break; } // Check if the error is retryable if (retryOptions.isRetryable && !retryOptions.isRetryable(lastError)) { break; } } } // If we get here, all retries failed if (lastError) { throw lastError; } // This should never happen, but TypeScript needs it throw new Error('Retry failed for unknown reason'); } exports.retry = retry; /** * Calculate delay with exponential backoff and jitter * * @param attempt - Retry attempt number (1-based) * @param options - Retry options * @returns Delay in milliseconds */ function calculateDelay(attempt, options) { // Calculate base delay let delay = options.exponential ? Math.min(options.baseDelay * Math.pow(2, attempt - 1), options.maxDelay) : options.baseDelay; // Add jitter if (options.jitter > 0) { const jitterAmount = delay * options.jitter; delay = delay - jitterAmount + Math.random() * jitterAmount * 2; } return Math.min(delay, options.maxDelay); } /** * Sleep for a specified duration * * @param ms - Duration in milliseconds * @returns Promise that resolves after the specified duration */ function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } //# sourceMappingURL=retry.js.map