UNPKG

digital-samba-mcp-server

Version:

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

213 lines 7.91 kB
/** * Digital Samba API Client with Graceful Degradation Integration * * This module integrates the graceful degradation pattern with the Digital Samba API client * and circuit breaker for comprehensive resilience strategies. * * Key features: * - Combines circuit breaker pattern with graceful degradation strategies * - Provides fallback mechanisms for API operations during outages * - Implements cache-based fallbacks for degraded service * - Features intelligent retry mechanisms with exponential backoff * - Includes health monitoring and metrics integration * * @module digital-samba-api-resilient * @author Digital Samba Team * @version 0.1.0 */ // Local modules import { DigitalSambaApiClient, } from './digital-samba-api.js'; import { CircuitBreakerApiClient } from './digital-samba-api-circuit-breaker.js'; import logger from './logger.js'; import { gracefulDegradation } from './graceful-degradation.js'; /** * Digital Samba API client with resilience patterns * * This class combines the circuit breaker and graceful degradation patterns * to provide comprehensive resilience for the Digital Samba API client. */ export class ResilientApiClient { /** * Creates a new resilient API client * * @param apiClient The Digital Samba API client to wrap * @param options Configuration options */ constructor(apiClient, options = {}) { this.options = options; this.cache = options.cache; // Create circuit breaker client this.circuitBreakerClient = CircuitBreakerApiClient.withCircuitBreaker(apiClient, { circuitPrefix: options.circuitBreaker?.circuitPrefix || 'api', defaultOptions: { failureThreshold: options.circuitBreaker?.failureThreshold || 3, resetTimeout: options.circuitBreaker?.resetTimeout || 30000, successThreshold: options.circuitBreaker?.successThreshold || 2, requestTimeout: options.circuitBreaker?.requestTimeout || 10000, initialRequestTimeout: options.circuitBreaker?.initialRequestTimeout || 30000 } }); // Register fallbacks this.registerFallbacks(options.fallbacks || {}); logger.debug('Created resilient API client', { hasCache: !!this.cache, circuitBreakerOptions: options.circuitBreaker, gracefulDegradationOptions: options.gracefulDegradation, fallbackCount: Object.keys(options.fallbacks || {}).length }); } /** * Register fallbacks for operations * * @private * @param fallbacks Fallback configurations */ registerFallbacks(fallbacks) { // Register standard fallbacks // Fallback for listRooms if (!fallbacks.listRooms) { fallbacks.listRooms = { fallbackFn: async () => ({ data: [], total_count: 0, length: 0, map: () => [] }), isCritical: true, cacheTTL: 600000 // 10 minutes }; } // Register all fallbacks with graceful degradation service for (const [operation, config] of Object.entries(fallbacks)) { if (config) { gracefulDegradation.registerFallback(operation, config); logger.info(`Registered fallback for operation: ${operation}`, { isCritical: config.isCritical, cacheTTL: config.cacheTTL }); } } } /** * List all rooms with resilience * * @param params Pagination parameters * @returns Rooms response */ async listRooms(params) { const result = await gracefulDegradation.executeWithFallback('listRooms', () => this.circuitBreakerClient.listRooms(params), { cacheKey: 'listRooms', cacheTTL: 300000 // 5 minutes }); return result.data; } /** * Get a specific room with resilience * * @param roomId Room ID * @returns Room details */ async getRoom(roomId) { const result = await gracefulDegradation.executeWithFallback('getRoom', () => this.circuitBreakerClient.getRoom(roomId), { cacheKey: `getRoom-${roomId}`, cacheTTL: 300000 // 5 minutes }); return result.data; } /** * Create a new room with resilience * * @param settings Room creation settings * @returns Created room */ async createRoom(settings) { const result = await gracefulDegradation.executeWithFallback('createRoom', () => this.circuitBreakerClient.createRoom(settings), { skipCache: true // Don't cache write operations }); return result.data; } /** * Update an existing room with resilience * * @param roomId Room ID * @param settings Room update settings * @returns Updated room */ async updateRoom(roomId, settings) { const result = await gracefulDegradation.executeWithFallback('updateRoom', () => this.circuitBreakerClient.updateRoom(roomId, settings), { skipCache: true // Don't cache write operations }); // Invalidate cached room if successful if (!result.isDegraded && this.cache) { this.cache.invalidate('degradation', `getRoom-${roomId}`); } return result.data; } /** * Delete a room with resilience * * @param roomId Room ID * @param options Delete options */ async deleteRoom(roomId, options) { const result = await gracefulDegradation.executeWithFallback('deleteRoom', () => this.circuitBreakerClient.deleteRoom(roomId, options), { skipCache: true // Don't cache write operations }); // Invalidate cached room if successful if (!result.isDegraded && this.cache) { this.cache.invalidate('degradation', `getRoom-${roomId}`); this.cache.invalidate('degradation', 'listRooms'); } return result.data; } /** * Generate a room token with resilience * * @param roomId Room ID * @param options Token options * @returns Token response */ async generateRoomToken(roomId, options) { const result = await gracefulDegradation.executeWithFallback('generateRoomToken', () => this.circuitBreakerClient.generateRoomToken(roomId, options), { skipCache: true // Security tokens should not be cached }); return result.data; } /** * Get system health status * * @returns System health status */ getSystemHealth() { const overall = gracefulDegradation.getOverallHealth(); const components = gracefulDegradation.getComponentHealth(); return { overall, components }; } /** * Create a resilient API client from a standard Digital Samba API client * * @param apiClient Digital Samba API client * @param options Resilient API client options * @returns A new resilient API client */ static withResilience(apiClient, options = {}) { return new ResilientApiClient(apiClient, options); } /** * Create a new resilient API client with the given API key * * @param apiKey API key * @param apiBaseUrl API base URL * @param options Resilient API client options * @returns A new resilient API client */ static createWithApiKey(apiKey, apiBaseUrl, options = {}) { const apiClient = new DigitalSambaApiClient(apiKey, apiBaseUrl, options.cache); return ResilientApiClient.withResilience(apiClient, options); } } export default ResilientApiClient; //# sourceMappingURL=digital-samba-api-resilient.js.map