UNPKG

digital-samba-mcp-server

Version:

Digital Samba MCP Server - Model Context Protocol server for Digital Samba's video conferencing API

316 lines 11 kB
/** * Circuit Breaker Pattern Implementation * * This module provides a circuit breaker implementation for handling API calls * in a fault-tolerant manner. The circuit breaker pattern prevents cascading failures * by breaking the circuit when a service is failing, and only attempting to restore * the connection after a specified timeout. * * Key features: * - Three states: CLOSED (normal operation), OPEN (failing, no requests), HALF_OPEN (testing recovery) * - Configurable thresholds for failure count, timeouts, and success count for reset * - Event hooks for state changes and failures * - Support for fallback handlers when the circuit is open * - Metrics integration for monitoring circuit state and events * * @module circuit-breaker * @author Digital Samba Team * @version 0.1.0 */ import { EventEmitter } from 'events'; /** * Circuit state enumeration * * CLOSED: Normal operation, requests pass through * OPEN: Circuit is broken, no requests pass through * HALF_OPEN: Testing if service has recovered */ export declare enum CircuitState { CLOSED = "CLOSED", OPEN = "OPEN", HALF_OPEN = "HALF_OPEN" } /** * Circuit breaker options interface */ export interface CircuitBreakerOptions { /** * The name of the circuit breaker (for logging and metrics) */ name: string; /** * Number of consecutive failures required to open the circuit * @default 5 */ failureThreshold?: number; /** * Time in milliseconds to wait before trying to half-open the circuit * @default 30000 (30 seconds) */ resetTimeout?: number; /** * Number of consecutive successful requests required to close the circuit from half-open state * @default 2 */ successThreshold?: number; /** * Time in milliseconds after which a request is considered a timeout failure * If not specified, timeouts will not be detected by the circuit breaker */ requestTimeout?: number; /** * Timeout for the initial request during circuit initialization * This should be longer than the regular requestTimeout to allow time for startup * @default 30000 (30 seconds) */ initialRequestTimeout?: number; /** * Callback function to determine if an error should be counted as a failure * @param error - The error to check * @returns true if the error should be counted as a failure, false otherwise * @default All errors are counted as failures */ isFailure?: (error: unknown) => boolean; /** * Fallback function to call when the circuit is open * @param params - The parameters that would have been passed to the protected function * @returns The fallback result */ fallback?: <T, Args extends any[]>(params: Args) => Promise<T>; } /** * Circuit breaker implementation for handling API calls * * The CircuitBreaker class implements the circuit breaker pattern to prevent * cascading failures when a service is experiencing issues. It monitors * failures and opens the circuit when a threshold is reached, allowing * the service time to recover. * * @class CircuitBreaker * @example * // Create a circuit breaker for a specific API endpoint * const circuitBreaker = new CircuitBreaker({ * name: 'listRooms', * failureThreshold: 3, * resetTimeout: 10000, * successThreshold: 2, * fallback: async () => ({ data: [], total_count: 0, length: 0, map: () => [] }) * }); * * // Protect a function call with the circuit breaker * const rooms = await circuitBreaker.exec(() => apiClient.listRooms()); */ export declare class CircuitBreaker extends EventEmitter { private name; private state; private failureCount; private successCount; private lastError; private nextAttempt; private failureThreshold; private resetTimeout; private successThreshold; private requestTimeout?; private initialRequestTimeout; private isFailure; private fallback?; /** * Creates a new CircuitBreaker instance * * @constructor * @param {CircuitBreakerOptions} options - Configuration options for the circuit breaker */ constructor(options: CircuitBreakerOptions); /** * Get the current state of the circuit * * @returns {CircuitState} The current circuit state */ getState(): CircuitState; /** * Get the name of the circuit * * @returns {string} The circuit name */ getName(): string; /** * Get the last error that occurred * * @returns {Error | null} The last error or null if no errors have occurred */ getLastError(): Error | null; /** * Execute a function with circuit breaker protection * * This method wraps the provided function with circuit breaker logic. * If the circuit is open, the function will not be called and an error will be thrown * (or the fallback will be used if provided). In CLOSED or HALF_OPEN states, * the function will be called and the result will be monitored for success or failure. * * @template T - The return type of the function * @template Args - The argument types of the function * @param {() => Promise<T>} fn - The function to protect * @param {Args} args - Arguments to pass to the function (as an array) * @param {boolean} [forceNoTimeout=false] - If true, disables the timeout for this call * @param {boolean} [isInitialization=false] - If true, treats this as an initialization request with special handling * @returns {Promise<T>} The result of the function or fallback * @throws {Error} If the circuit is open and no fallback is provided * @example * // Protect an API call * const result = await circuitBreaker.exec( * async () => { return await fetch('https://api.example.com/data'); }, * [] // No args * ); */ exec<T, Args extends any[]>(fn: () => Promise<T>, args?: Args, forceNoTimeout?: boolean, isInitialization?: boolean): Promise<T>; /** * Handle a successful execution * * @private */ private handleSuccess; /** * Handle a failure * * @private * @param {Error} error - The error that occurred */ private handleFailure; /** * Transition the circuit to the OPEN state * * @private */ private toOpen; /** * Transition the circuit to the HALF_OPEN state * * @private */ private toHalfOpen; /** * Transition the circuit to the CLOSED state * * @private */ private toClosed; /** * Reset the circuit to the CLOSED state regardless of current state * * This method can be called externally to force the circuit back to normal operation. * This is useful for manual intervention after investigating and resolving an issue. */ reset(): void; /** * Force the circuit to the OPEN state * * This method can be called externally to force the circuit to the OPEN state. * This is useful for pre-emptively stopping traffic to a service that is known to be down. * * @param {Error} [error] - Optional error to store as the last error */ trip(error?: Error): void; /** * Update metrics for the circuit breaker * * This method attempts to update Prometheus metrics if the metrics module is available. * If the metrics module cannot be imported, the method silently ignores the error. * * @private * @param {string} event - The event type ('created', 'success', 'failure', 'state_change', 'reset', 'trip') * @param {Record<string, any>} [labels] - Additional labels for the metric */ private updateMetrics; } /** * Circuit breaker registry to manage multiple circuit breakers * * This class provides a registry for managing multiple circuit breakers * with convenient methods for creation, retrieval, and management. * * @class CircuitBreakerRegistry * @example * // Get the global registry * const registry = CircuitBreakerRegistry.getInstance(); * * // Create a new circuit breaker * const listRoomsCircuit = registry.create({ * name: 'listRooms', * failureThreshold: 3 * }); * * // Get an existing circuit breaker * const circuit = registry.get('listRooms'); * * // Execute a function with the circuit breaker * const rooms = await circuit.exec(() => apiClient.listRooms()); */ export declare class CircuitBreakerRegistry extends EventEmitter { private static instance; private circuits; /** * Private constructor to enforce singleton pattern * * @private */ private constructor(); /** * Get the singleton instance of the registry * * @returns {CircuitBreakerRegistry} The singleton registry instance */ static getInstance(): CircuitBreakerRegistry; /** * Create a new circuit breaker and add it to the registry * * @param {CircuitBreakerOptions} options - Options for the new circuit breaker * @returns {CircuitBreaker} The newly created circuit breaker * @throws {Error} If a circuit breaker with the same name already exists */ create(options: CircuitBreakerOptions): CircuitBreaker; /** * Get a circuit breaker from the registry * * @param {string} name - The name of the circuit breaker to retrieve * @returns {CircuitBreaker | undefined} The circuit breaker or undefined if not found */ get(name: string): CircuitBreaker | undefined; /** * Get or create a circuit breaker * * If a circuit breaker with the given name exists, it will be returned. * Otherwise, a new circuit breaker will be created with the provided options. * * @param {CircuitBreakerOptions} options - Options for the circuit breaker * @returns {CircuitBreaker} The existing or newly created circuit breaker */ getOrCreate(options: CircuitBreakerOptions): CircuitBreaker; /** * Remove a circuit breaker from the registry * * @param {string} name - The name of the circuit breaker to remove * @returns {boolean} True if the circuit breaker was removed, false if it was not found */ remove(name: string): boolean; /** * Get all circuit breakers in the registry * * @returns {CircuitBreaker[]} An array of all circuit breakers */ getAll(): CircuitBreaker[]; /** * Get the count of circuit breakers in the registry * * @returns {number} The number of circuit breakers */ getCount(): number; /** * Reset all circuit breakers to the CLOSED state * * This is useful for system restarts or after resolving a widespread issue. */ resetAll(): void; } export declare const circuitBreakerRegistry: CircuitBreakerRegistry; export default circuitBreakerRegistry; //# sourceMappingURL=circuit-breaker.d.ts.map