UNPKG

trainingpeaks-sdk

Version:
87 lines (86 loc) 3.4 kB
import { isRetryableError } from '../../adapters/errors/http-errors.js'; export class RetryHandler { constructor(config) { this.config = config; this.config = { maxDelay: 30000, jitter: true, ...config, }; } async execute(operation, context) { let lastError; for (let attempt = 1; attempt <= this.config.attempts; attempt++) { try { if (attempt > 1 && context?.logger) { context.logger.warn('Retrying HTTP request', { requestId: context.requestId, attempt, totalAttempts: this.config.attempts, url: context.url, method: context.method, }); } return await operation(); } catch (error) { lastError = error; if (attempt === this.config.attempts || !isRetryableError(error)) { if (context?.logger) { context.logger.error('HTTP request failed after retries', { requestId: context.requestId, finalAttempt: attempt, totalAttempts: this.config.attempts, url: context.url, method: context.method, error: error instanceof Error ? error.message : String(error), errorCode: error && typeof error === 'object' && 'code' in error ? error.code : undefined, retryable: isRetryableError(error), }); } throw error; } const delay = this.calculateDelay(attempt); if (context?.logger) { context.logger.info('HTTP request failed, will retry', { requestId: context.requestId, attempt, totalAttempts: this.config.attempts, nextRetryIn: `${Math.round(delay)}ms`, url: context.url, method: context.method, error: error instanceof Error ? error.message : String(error), errorCode: error && typeof error === 'object' && 'code' in error ? error.code : undefined, }); } await this.delay(attempt); } } throw lastError; } calculateDelay(attempt) { let delay = this.config.delay * Math.pow(this.config.backoff, attempt - 1); if (this.config.maxDelay) { delay = Math.min(delay, this.config.maxDelay); } if (this.config.jitter) { delay = delay * (0.5 + Math.random() * 0.5); } return delay; } async delay(attempt) { const delay = this.calculateDelay(attempt); return new Promise((resolve) => setTimeout(resolve, Math.round(delay))); } } export const DEFAULT_RETRY_CONFIG = { attempts: 3, delay: 1000, backoff: 2, maxDelay: 10000, jitter: true, };