llm_incident_manager/circuit_breaker/
mod.rs1mod 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
60pub type CircuitBreakerResult<T> = std::result::Result<T, CircuitBreakerError>;
62
63#[derive(Debug, thiserror::Error)]
65pub enum CircuitBreakerError {
66 #[error("Circuit breaker is open for '{0}'")]
68 Open(String),
69
70 #[error("Invalid configuration: {0}")]
72 InvalidConfig(String),
73
74 #[error("Operation failed: {0}")]
76 OperationFailed(String),
77
78 #[error("Operation timed out")]
80 Timeout,
81
82 #[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}