UNPKG

md-linear-sync

Version:

Sync Linear tickets to local markdown files with status-based folder organization

98 lines 4.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RetryManager = void 0; class RetryManager { static async withRetry(operation, config = {}, operationName = 'operation') { const finalConfig = { ...this.DEFAULT_CONFIG, ...config }; let lastError; for (let attempt = 0; attempt < finalConfig.maxAttempts; attempt++) { try { if (attempt > 0) { const delay = finalConfig.delays[attempt - 1] || finalConfig.delays[finalConfig.delays.length - 1]; console.log(`⏱️ Retrying ${operationName} in ${delay}ms (attempt ${attempt + 1}/${finalConfig.maxAttempts})`); await this.sleep(delay); } const result = await operation(); if (attempt > 0) { console.log(`✅ ${operationName} succeeded on attempt ${attempt + 1}`); } return result; } catch (error) { lastError = error instanceof Error ? error : new Error(String(error)); // Check if error is retryable if (!this.isRetryableError(lastError)) { console.log(`❌ ${operationName} failed with non-retryable error: ${lastError.message}`); throw lastError; } console.log(`⚠️ ${operationName} failed (attempt ${attempt + 1}): ${lastError.message}`); // If this is the last attempt, throw the error if (attempt === finalConfig.maxAttempts - 1) { console.log(`❌ ${operationName} failed after ${finalConfig.maxAttempts} attempts`); throw lastError; } } } throw lastError; } static isRetryableError(error) { const message = error.message.toLowerCase(); // Network errors - retry if (message.includes('network') || message.includes('timeout') || message.includes('connection') || message.includes('econnreset') || message.includes('enotfound')) { return true; } // Rate limiting - retry if (message.includes('rate limit') || message.includes('too many requests') || message.includes('429')) { return true; } // Server errors (5xx) - retry if (message.includes('500') || message.includes('502') || message.includes('503') || message.includes('504') || message.includes('internal server error') || message.includes('bad gateway') || message.includes('service unavailable') || message.includes('gateway timeout')) { return true; } // Authentication/authorization errors - don't retry if (message.includes('unauthorized') || message.includes('forbidden') || message.includes('invalid api key') || message.includes('401') || message.includes('403')) { return false; } // Validation errors - don't retry if (message.includes('validation') || message.includes('invalid') || message.includes('bad request') || message.includes('400')) { return false; } // File system errors - don't retry (mostly) if (message.includes('enoent') || message.includes('permission denied') || message.includes('eacces')) { return false; } // Unknown errors - be conservative and retry return true; } static sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } } exports.RetryManager = RetryManager; RetryManager.DEFAULT_CONFIG = { maxAttempts: 3, delays: [0, 30000, 120000] // immediate, 30s, 2min }; //# sourceMappingURL=RetryManager.js.map