llm_incident_manager/circuit_breaker/
mod.rs

1//! Production-ready Circuit Breaker implementation for fault tolerance.
2//!
3//! This module provides a comprehensive circuit breaker pattern implementation with:
4//! - Thread-safe state management
5//! - Prometheus metrics integration
6//! - Async/await support
7//! - Configurable failure thresholds
8//! - Automatic recovery detection
9//! - Fallback support
10//! - Global registry for circuit breaker management
11//!
12//! # Circuit Breaker States
13//!
14//! - **Closed**: Normal operation, requests pass through, failures are counted
15//! - **Open**: Fast-fail mode, all requests are rejected immediately
16//! - **Half-Open**: Testing recovery, limited requests are allowed to test if the service recovered
17//!
18//! # Example
19//!
20//! ```no_run
21//! use llm_incident_manager::circuit_breaker::{CircuitBreaker, CircuitBreakerConfig};
22//!
23//! #[tokio::main]
24//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
25//!     let config = CircuitBreakerConfig::builder()
26//!         .failure_threshold(5)
27//!         .timeout_duration(std::time::Duration::from_secs(60))
28//!         .build()?;
29//!
30//!     let breaker = CircuitBreaker::new("my-service", config);
31//!
32//!     // Execute a protected operation
33//!     let result = breaker.call(|| async {
34//!         // Your async operation here
35//!         Ok::<_, std::io::Error>(42)
36//!     }).await;
37//!
38//!     Ok(())
39//! }
40//! ```
41
42mod config;
43mod core;
44mod decorators;
45mod metrics;
46mod middleware;
47mod registry;
48mod state;
49
50pub use config::{CircuitBreakerConfig, CircuitBreakerConfigBuilder};
51pub use core::CircuitBreaker;
52pub use decorators::{with_circuit_breaker, CircuitBreakerDecorator};
53pub use metrics::{init_circuit_breaker_metrics, CIRCUIT_BREAKER_METRICS};
54pub use middleware::CircuitBreakerMiddleware;
55pub use registry::{get_circuit_breaker, CircuitBreakerRegistry, GLOBAL_CIRCUIT_BREAKER_REGISTRY};
56pub use state::{CircuitBreakerState, StateData, StateTransition};
57
58use crate::error::AppError;
59
60/// Result type for circuit breaker operations
61pub type CircuitBreakerResult<T> = std::result::Result<T, CircuitBreakerError>;
62
63/// Errors that can occur in circuit breaker operations
64#[derive(Debug, thiserror::Error)]
65pub enum CircuitBreakerError {
66    /// Circuit is open and rejecting requests
67    #[error("Circuit breaker is open for '{0}'")]
68    Open(String),
69
70    /// Configuration is invalid
71    #[error("Invalid configuration: {0}")]
72    InvalidConfig(String),
73
74    /// Operation failed
75    #[error("Operation failed: {0}")]
76    OperationFailed(String),
77
78    /// Timeout occurred
79    #[error("Operation timed out")]
80    Timeout,
81
82    /// Circuit breaker not found in registry
83    #[error("Circuit breaker '{0}' not found")]
84    NotFound(String),
85}
86
87impl From<CircuitBreakerError> for AppError {
88    fn from(err: CircuitBreakerError) -> Self {
89        match err {
90            CircuitBreakerError::Open(name) => {
91                AppError::Internal(format!("Circuit breaker open: {}", name))
92            }
93            CircuitBreakerError::InvalidConfig(msg) => AppError::Configuration(msg),
94            CircuitBreakerError::OperationFailed(msg) => AppError::Internal(msg),
95            CircuitBreakerError::Timeout => AppError::Timeout("Circuit breaker timeout".to_string()),
96            CircuitBreakerError::NotFound(name) => {
97                AppError::NotFound(format!("Circuit breaker: {}", name))
98            }
99        }
100    }
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106
107    #[test]
108    fn test_circuit_breaker_error_conversion() {
109        let err = CircuitBreakerError::Open("test-service".to_string());
110        let app_err: AppError = err.into();
111        assert!(matches!(app_err, AppError::Internal(_)));
112    }
113}