UNPKG

chronik-cache

Version:

A cache helper for chronik-client

87 lines (76 loc) 3.25 kB
// Copyright (c) 2024 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. import Logger from './Logger'; interface FailoverOptions { maxRetries?: number; retryDelay?: number; exponentialBackoff?: boolean; enableLogging?: boolean; } export default class FailoverHandler { private maxRetries: number; private retryDelay: number; private exponentialBackoff: boolean; private enableLogging: boolean; private logger: Logger; constructor(options: FailoverOptions = {}) { this.maxRetries = options.maxRetries || 3; this.retryDelay = options.retryDelay || 1500; // milliseconds this.exponentialBackoff = options.exponentialBackoff ?? true; this.enableLogging = options.enableLogging ?? false; this.logger = new Logger(this.enableLogging); } async executeWithRetry<T>(operation: () => Promise<T>, context: string = ''): Promise<T> { let lastError: Error; for (let attempt = 1; attempt <= this.maxRetries; attempt++) { try { return await operation(); } catch (error) { lastError = error as Error; const delay = this.exponentialBackoff ? this.retryDelay * Math.pow(2, attempt - 1) : this.retryDelay; this.logger.error(`[Failover] ${context} - Attempt ${attempt}/${this.maxRetries} failed:`, lastError.message); if (attempt < this.maxRetries) { this.logger.log(`[Failover] Retrying in ${delay}ms...`); await new Promise(resolve => setTimeout(resolve, delay)); } } } this.logger.error(`[Failover] ${context} - All retry attempts failed`); throw lastError!; } /** * Special handling for WebSocket related operations */ async handleWebSocketOperation<T>(operation: () => Promise<T>, address: string, context: string = ''): Promise<T> { try { return await this.executeWithRetry(operation, context); } catch (error) { const err = error as any; this.logger.error(`[Failover] WebSocket operation failed for address ${address}:`, err.message); // WebSocket specific error handling logic if (err.code === 'ECONNREFUSED' || err.code === 'ECONNRESET') { this.logger.log(`[Failover] WebSocket connection issue detected for ${address}`); } throw error; } } /** * Special handling for database operations */ async handleDbOperation<T>(operation: () => Promise<T>, context: string = ''): Promise<T | null> { try { return await this.executeWithRetry(operation, context); } catch (error) { const err = error as any; this.logger.error(`[Failover] Database operation failed:`, err.message); // Database specific error handling logic if (err.type === 'NotFoundError') { return null; } throw error; } } }