UNPKG

@dbs-portal/core-api

Version:

HTTP client and API utilities for DBS Portal

206 lines 6.27 kB
/** * Retry manager for failed requests */ /** * Default retry condition - retry on network errors and 5xx status codes */ const defaultRetryCondition = (error) => { if (!error.response) { // Network error return true; } const status = error.response.status; // Retry on 5xx server errors if (status >= 500 && status < 600) { return true; } // Retry on specific 4xx errors if (status === 408 || status === 429) { return true; } return false; }; /** * Default retry delay - exponential backoff */ const defaultRetryDelay = (retryCount) => { return Math.min(1000 * Math.pow(2, retryCount), 30000); // Max 30 seconds }; /** * Retry manager for handling failed requests */ export class RetryManager { config; constructor(config) { this.config = { retries: config.retries, retryDelay: config.retryDelay || defaultRetryDelay, retryCondition: config.retryCondition || defaultRetryCondition, shouldResetTimeout: config.shouldResetTimeout ?? true, }; } /** * Executes a function with retry logic */ async execute(operation) { let lastError; let retryCount = 0; while (retryCount <= this.config.retries) { try { return await operation(); } catch (error) { lastError = error; // Check if we should retry if (retryCount >= this.config.retries || !this.shouldRetry(error)) { break; } // Calculate delay const delay = this.calculateDelay(retryCount); // Wait before retrying if (delay > 0) { await this.delay(delay); } retryCount++; } } throw lastError; } /** * Updates retry configuration */ updateConfig(config) { this.config = { ...this.config, ...config, retryDelay: config.retryDelay || this.config.retryDelay, retryCondition: config.retryCondition || this.config.retryCondition, }; } /** * Gets current configuration */ getConfig() { return { ...this.config }; } /** * Determines if an error should trigger a retry */ shouldRetry(error) { return this.config.retryCondition(error); } /** * Calculates retry delay */ calculateDelay(retryCount) { if (typeof this.config.retryDelay === 'function') { return this.config.retryDelay(retryCount); } return this.config.retryDelay; } /** * Creates a delay promise */ delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } /** * Creates a retry manager with exponential backoff */ static exponentialBackoff(retries = 3, baseDelay = 1000, maxDelay = 30000) { return new RetryManager({ retries, retryDelay: retryCount => Math.min(baseDelay * Math.pow(2, retryCount), maxDelay), retryCondition: defaultRetryCondition, }); } /** * Creates a retry manager with linear backoff */ static linearBackoff(retries = 3, delay = 1000) { return new RetryManager({ retries, retryDelay: retryCount => delay * (retryCount + 1), retryCondition: defaultRetryCondition, }); } /** * Creates a retry manager with fixed delay */ static fixedDelay(retries = 3, delay = 1000) { return new RetryManager({ retries, retryDelay: delay, retryCondition: defaultRetryCondition, }); } /** * Creates a retry manager for network errors only */ static networkErrorsOnly(retries = 3) { return new RetryManager({ retries, retryDelay: defaultRetryDelay, retryCondition: error => !error.response, // Only network errors }); } /** * Creates a retry manager for server errors only */ static serverErrorsOnly(retries = 3) { return new RetryManager({ retries, retryDelay: defaultRetryDelay, retryCondition: error => { const status = error.response?.status; return status ? status >= 500 && status < 600 : false; }, }); } /** * Creates a retry manager with custom condition */ static custom(retries, retryCondition, retryDelay) { return new RetryManager({ retries, retryCondition, retryDelay: retryDelay || defaultRetryDelay, }); } /** * Creates a retry manager that respects Retry-After headers */ static withRetryAfter(retries = 3) { return new RetryManager({ retries, retryCondition: defaultRetryCondition, retryDelay: (retryCount, error) => { // Check for Retry-After header const retryAfter = error?.response?.headers?.['retry-after']; if (retryAfter) { const seconds = Number.parseInt(retryAfter, 10); if (!isNaN(seconds)) { return seconds * 1000; // Convert to milliseconds } } // Fallback to exponential backoff return defaultRetryDelay(retryCount); }, }); } /** * Creates a retry manager with jitter to avoid thundering herd */ static withJitter(retries = 3, baseDelay = 1000, maxDelay = 30000, jitterFactor = 0.1) { return new RetryManager({ retries, retryCondition: defaultRetryCondition, retryDelay: retryCount => { const exponentialDelay = Math.min(baseDelay * Math.pow(2, retryCount), maxDelay); const jitter = exponentialDelay * jitterFactor * Math.random(); return exponentialDelay + jitter; }, }); } } //# sourceMappingURL=retry-manager.js.map