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
JavaScript
/**
* 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