digital-samba-mcp-server
Version:
Digital Samba MCP Server - Model Context Protocol server for Digital Samba's video conferencing API
316 lines • 11 kB
TypeScript
/**
* 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