{"version":3,"file":"realtime-circuit-breaker.mjs","sources":["../../../src/lib/realtime/realtime-circuit-breaker.ts"],"sourcesContent":["/**\n * @file Realtime Circuit Breaker\n * @description Circuit breaker wrapper for WebSocket and SSE connections\n * to prevent connection storms and provide graceful degradation\n */\n\nimport { CircuitBreaker, type CircuitState, CircuitOpenError } from '../utils/resilience';\n\n/**\n * Realtime circuit breaker configuration\n */\nexport interface RealtimeCircuitBreakerConfig {\n  /** Failure threshold before opening circuit */\n  failureThreshold?: number;\n  /** Success threshold for half-open to close */\n  successThreshold?: number;\n  /** Time to wait before trying half-open (ms) */\n  resetTimeout?: number;\n  /** Time window for failure counting (ms) */\n  failureWindow?: number;\n  /** Connection timeout (ms) */\n  connectionTimeout?: number;\n  /** Whether to enable health checking */\n  healthCheckEnabled?: boolean;\n  /** Health check interval (ms) */\n  healthCheckInterval?: number;\n  /** Callback on state change */\n  onStateChange?: (from: CircuitState, to: CircuitState) => void;\n  /** Callback when circuit opens (for fallback logic) */\n  onCircuitOpen?: () => void;\n  /** Callback when circuit recovers */\n  onCircuitRecovery?: () => void;\n}\n\n/**\n * Default configuration for realtime circuit breaker\n */\nconst DEFAULT_CONFIG: Required<\n  Omit<RealtimeCircuitBreakerConfig, 'onStateChange' | 'onCircuitOpen' | 'onCircuitRecovery'>\n> = {\n  failureThreshold: 3,\n  successThreshold: 1,\n  resetTimeout: 300000, // 5 minutes - longer for realtime connections\n  failureWindow: 60000, // 1 minute\n  connectionTimeout: 10000, // 10 seconds\n  healthCheckEnabled: true,\n  healthCheckInterval: 60000, // 1 minute\n};\n\n/**\n * Connection state\n */\nexport type RealtimeConnectionState =\n  | 'disconnected'\n  | 'connecting'\n  | 'connected'\n  | 'reconnecting'\n  | 'circuit_open'\n  | 'degraded';\n\n/**\n * Connection metrics\n */\nexport interface RealtimeConnectionMetrics {\n  consecutiveFailures: number;\n  totalFailures: number;\n  totalSuccesses: number;\n  lastFailureTime: Date | null;\n  lastSuccessTime: Date | null;\n  circuitState: CircuitState;\n  connectionState: RealtimeConnectionState;\n  averageReconnectTime: number;\n}\n\n/**\n * Realtime circuit breaker for WebSocket/SSE connections\n *\n * This class provides fault isolation for realtime connections:\n * - Prevents connection storms during outages\n * - Provides graceful degradation when services are unavailable\n * - Tracks connection health metrics\n * - Supports fallback to alternative transports\n */\nexport class RealtimeCircuitBreaker {\n  private breaker: CircuitBreaker;\n  private config: Required<\n    Omit<RealtimeCircuitBreakerConfig, 'onStateChange' | 'onCircuitOpen' | 'onCircuitRecovery'>\n  > & {\n    onStateChange?: RealtimeCircuitBreakerConfig['onStateChange'];\n    onCircuitOpen?: RealtimeCircuitBreakerConfig['onCircuitOpen'];\n    onCircuitRecovery?: RealtimeCircuitBreakerConfig['onCircuitRecovery'];\n  };\n  private connectionState: RealtimeConnectionState = 'disconnected';\n  private consecutiveFailures = 0;\n  private totalFailures = 0;\n  private totalSuccesses = 0;\n  private lastFailureTime: number | null = null;\n  private lastSuccessTime: number | null = null;\n  private reconnectTimes: number[] = [];\n  private healthCheckTimer: ReturnType<typeof setInterval> | null = null;\n  private connectionStartTime: number | null = null;\n  private disposed = false;\n\n  constructor(config: RealtimeCircuitBreakerConfig = {}) {\n    this.config = {\n      ...DEFAULT_CONFIG,\n      ...config,\n    };\n\n    this.breaker = new CircuitBreaker({\n      failureThreshold: this.config.failureThreshold,\n      successThreshold: this.config.successThreshold,\n      resetTimeout: this.config.resetTimeout,\n      failureWindow: this.config.failureWindow,\n      onStateChange: (from, to) => {\n        this.handleCircuitStateChange(from, to);\n        this.config.onStateChange?.(from, to);\n      },\n    });\n  }\n\n  /**\n   * Get current circuit state\n   */\n  getCircuitState(): CircuitState {\n    return this.breaker.getState();\n  }\n\n  /**\n   * Get current connection state\n   */\n  getConnectionState(): RealtimeConnectionState {\n    return this.connectionState;\n  }\n\n  /**\n   * Check if connection is allowed\n   */\n  canConnect(): boolean {\n    const state = this.breaker.getState();\n    return state !== 'open';\n  }\n\n  /**\n   * Check if circuit is open\n   */\n  isCircuitOpen(): boolean {\n    return this.breaker.getState() === 'open';\n  }\n\n  /**\n   * Execute a connection attempt through the circuit breaker\n   */\n  async connect<T>(\n    connectionFactory: () => Promise<T>,\n    options: { timeout?: number } = {}\n  ): Promise<T> {\n    if (this.disposed) {\n      throw new Error('Circuit breaker has been disposed');\n    }\n\n    const state = this.breaker.getState();\n\n    if (state === 'open') {\n      this.connectionState = 'circuit_open';\n      throw new CircuitOpenError('Realtime circuit breaker is open - connection blocked');\n    }\n\n    this.connectionState = 'connecting';\n    this.connectionStartTime = Date.now();\n    const timeout = options.timeout ?? this.config.connectionTimeout;\n\n    try {\n      const result = await this.withConnectionTimeout(connectionFactory, timeout);\n      this.recordSuccess();\n      return result;\n    } catch (error) {\n      this.recordFailure();\n      throw error;\n    }\n  }\n\n  /**\n   * Record a successful connection\n   */\n  recordSuccess(): void {\n    this.breaker.success();\n    this.consecutiveFailures = 0;\n    this.totalSuccesses++;\n    this.lastSuccessTime = Date.now();\n    this.connectionState = 'connected';\n\n    // Track reconnect time\n    if (this.connectionStartTime !== null) {\n      const reconnectTime = Date.now() - this.connectionStartTime;\n      this.reconnectTimes.push(reconnectTime);\n      // Keep only last 10 reconnect times\n      if (this.reconnectTimes.length > 10) {\n        this.reconnectTimes.shift();\n      }\n    }\n  }\n\n  /**\n   * Record a connection failure\n   */\n  recordFailure(): void {\n    this.breaker.failure();\n    this.consecutiveFailures++;\n    this.totalFailures++;\n    this.lastFailureTime = Date.now();\n\n    // Update connection state based on circuit state\n    const circuitState = this.breaker.getState();\n    if (circuitState === 'open') {\n      this.connectionState = 'circuit_open';\n    } else {\n      this.connectionState = 'reconnecting';\n    }\n  }\n\n  /**\n   * Record a disconnect event (not necessarily a failure)\n   */\n  recordDisconnect(): void {\n    if (this.connectionState === 'connected') {\n      this.connectionState = 'disconnected';\n    }\n  }\n\n  /**\n   * Get connection metrics\n   */\n  getMetrics(): RealtimeConnectionMetrics {\n    const averageReconnectTime =\n      this.reconnectTimes.length > 0\n        ? this.reconnectTimes.reduce((a, b) => a + b, 0) / this.reconnectTimes.length\n        : 0;\n\n    return {\n      consecutiveFailures: this.consecutiveFailures,\n      totalFailures: this.totalFailures,\n      totalSuccesses: this.totalSuccesses,\n      lastFailureTime: this.lastFailureTime !== null ? new Date(this.lastFailureTime) : null,\n      lastSuccessTime: this.lastSuccessTime !== null ? new Date(this.lastSuccessTime) : null,\n      circuitState: this.breaker.getState(),\n      connectionState: this.connectionState,\n      averageReconnectTime,\n    };\n  }\n\n  /**\n   * Start health checking (for monitoring purposes)\n   */\n  startHealthCheck(checkFn: () => Promise<boolean>): void {\n    if (!this.config.healthCheckEnabled || this.healthCheckTimer !== null) {\n      return;\n    }\n\n    this.healthCheckTimer = setInterval(() => {\n      void (async () => {\n        if (this.disposed) {\n          this.stopHealthCheck();\n          return;\n        }\n\n        try {\n          const isHealthy = await checkFn();\n          if (isHealthy) {\n            // Health check success in open state can trigger half-open\n            if (this.breaker.getState() === 'open') {\n              console.info('[RealtimeCircuitBreaker] Health check passed - circuit may recover');\n            }\n          } else {\n            // Health check failure while connected indicates degradation\n            if (this.connectionState === 'connected') {\n              this.connectionState = 'degraded';\n            }\n          }\n        } catch {\n          // Health check errors are logged but don't affect circuit state\n          console.warn('[RealtimeCircuitBreaker] Health check failed');\n        }\n      })();\n    }, this.config.healthCheckInterval);\n  }\n\n  /**\n   * Stop health checking\n   */\n  stopHealthCheck(): void {\n    if (this.healthCheckTimer !== null) {\n      clearInterval(this.healthCheckTimer);\n      this.healthCheckTimer = null;\n    }\n  }\n\n  /**\n   * Force reset the circuit breaker\n   */\n  reset(): void {\n    this.breaker.reset();\n    this.consecutiveFailures = 0;\n    this.connectionState = 'disconnected';\n    console.info('[RealtimeCircuitBreaker] Circuit manually reset');\n  }\n\n  /**\n   * Dispose the circuit breaker\n   */\n  dispose(): void {\n    this.disposed = true;\n    this.stopHealthCheck();\n    this.connectionState = 'disconnected';\n  }\n\n  /**\n   * Handle circuit state changes\n   */\n  private handleCircuitStateChange(from: CircuitState, to: CircuitState): void {\n    if (to === 'open') {\n      this.connectionState = 'circuit_open';\n      this.config.onCircuitOpen?.();\n      console.warn('[RealtimeCircuitBreaker] Circuit opened - stopping reconnection attempts');\n    } else if (from === 'open' && to === 'half-open') {\n      this.connectionState = 'reconnecting';\n      console.info('[RealtimeCircuitBreaker] Circuit half-open - attempting recovery');\n    } else if (to === 'closed' && from !== 'closed') {\n      this.config.onCircuitRecovery?.();\n      console.info('[RealtimeCircuitBreaker] Circuit recovered');\n    }\n  }\n\n  /**\n   * Apply timeout to connection factory\n   */\n  private async withConnectionTimeout<T>(\n    connectionFactory: () => Promise<T>,\n    timeout: number\n  ): Promise<T> {\n    return new Promise((resolve, reject) => {\n      const timeoutId = setTimeout(() => {\n        reject(new ConnectionTimeoutError(`Connection timed out after ${timeout}ms`));\n      }, timeout);\n\n      connectionFactory()\n        .then((result) => {\n          clearTimeout(timeoutId);\n          resolve(result);\n        })\n        .catch((error: unknown) => {\n          clearTimeout(timeoutId);\n          reject(error instanceof Error ? error : new Error(String(error)));\n        });\n    });\n  }\n}\n\n/**\n * Connection timeout error\n */\nexport class ConnectionTimeoutError extends Error {\n  readonly isConnectionTimeout = true;\n\n  constructor(message = 'Connection timed out') {\n    super(message);\n    this.name = 'ConnectionTimeoutError';\n  }\n}\n\n/**\n * Create a WebSocket-specific circuit breaker\n */\nexport function createWebSocketCircuitBreaker(\n  config?: RealtimeCircuitBreakerConfig\n): RealtimeCircuitBreaker {\n  return new RealtimeCircuitBreaker({\n    failureThreshold: 3,\n    successThreshold: 1,\n    resetTimeout: 300000, // 5 minutes\n    connectionTimeout: 10000,\n    ...config,\n  });\n}\n\n/**\n * Create an SSE-specific circuit breaker\n */\nexport function createSSECircuitBreaker(\n  config?: RealtimeCircuitBreakerConfig\n): RealtimeCircuitBreaker {\n  return new RealtimeCircuitBreaker({\n    failureThreshold: 3,\n    successThreshold: 1,\n    resetTimeout: 300000, // 5 minutes\n    connectionTimeout: 15000, // SSE connections may take longer\n    ...config,\n  });\n}\n\n/**\n * Global realtime circuit breaker registry\n */\nconst circuitBreakerRegistry = new Map<string, RealtimeCircuitBreaker>();\n\n/**\n * Get or create a named circuit breaker\n */\nexport function getRealtimeCircuitBreaker(\n  name: string,\n  config?: RealtimeCircuitBreakerConfig\n): RealtimeCircuitBreaker {\n  let breaker = circuitBreakerRegistry.get(name);\n\n  if (breaker === undefined) {\n    breaker = new RealtimeCircuitBreaker(config);\n    circuitBreakerRegistry.set(name, breaker);\n  }\n\n  return breaker;\n}\n\n/**\n * Reset all circuit breakers\n */\nexport function resetAllRealtimeCircuitBreakers(): void {\n  circuitBreakerRegistry.forEach((breaker) => {\n    breaker.reset();\n  });\n}\n\n/**\n * Get all circuit breaker metrics\n */\nexport function getAllRealtimeCircuitBreakerMetrics(): Record<string, RealtimeConnectionMetrics> {\n  const metrics: Record<string, RealtimeConnectionMetrics> = {};\n\n  circuitBreakerRegistry.forEach((breaker, name) => {\n    metrics[name] = breaker.getMetrics();\n  });\n\n  return metrics;\n}\n\n/**\n * Dispose all circuit breakers\n */\nexport function disposeAllRealtimeCircuitBreakers(): void {\n  circuitBreakerRegistry.forEach((breaker) => {\n    breaker.dispose();\n  });\n  circuitBreakerRegistry.clear();\n}\n"],"names":["DEFAULT_CONFIG","RealtimeCircuitBreaker","config","CircuitBreaker","from","to","connectionFactory","options","CircuitOpenError","timeout","result","error","reconnectTime","averageReconnectTime","a","b","checkFn","resolve","reject","timeoutId","ConnectionTimeoutError","message","createWebSocketCircuitBreaker","createSSECircuitBreaker","circuitBreakerRegistry","getRealtimeCircuitBreaker","name","breaker","resetAllRealtimeCircuitBreakers","getAllRealtimeCircuitBreakerMetrics","metrics","disposeAllRealtimeCircuitBreakers"],"mappings":"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"}