rustkernel_core/resilience/
mod.rs1pub mod circuit_breaker;
28pub mod health;
29pub mod recovery;
30pub mod timeout;
31
32pub use circuit_breaker::{CircuitBreaker, CircuitBreakerConfig, CircuitState};
33pub use health::{HealthCheck, HealthCheckResult, HealthProbe};
34pub use recovery::{RecoveryPolicy, RecoveryStrategy, RetryConfig};
35pub use timeout::{DeadlineContext, TimeoutConfig, TimeoutError};
36
37use serde::{Deserialize, Serialize};
38use std::time::Duration;
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct ResilienceConfig {
43 pub circuit_breaker: Option<CircuitBreakerConfig>,
45 pub timeout: Option<TimeoutConfig>,
47 pub recovery: Option<RecoveryPolicy>,
49 pub health_check_interval: Duration,
51}
52
53impl Default for ResilienceConfig {
54 fn default() -> Self {
55 Self {
56 circuit_breaker: Some(CircuitBreakerConfig::default()),
57 timeout: Some(TimeoutConfig::default()),
58 recovery: Some(RecoveryPolicy::default()),
59 health_check_interval: Duration::from_secs(10),
60 }
61 }
62}
63
64impl ResilienceConfig {
65 pub fn new() -> Self {
67 Self::default()
68 }
69
70 pub fn disabled() -> Self {
72 Self {
73 circuit_breaker: None,
74 timeout: None,
75 recovery: None,
76 health_check_interval: Duration::from_secs(60),
77 }
78 }
79
80 pub fn production() -> Self {
82 Self {
83 circuit_breaker: Some(CircuitBreakerConfig::production()),
84 timeout: Some(TimeoutConfig::production()),
85 recovery: Some(RecoveryPolicy::production()),
86 health_check_interval: Duration::from_secs(10),
87 }
88 }
89
90 pub fn development() -> Self {
92 Self {
93 circuit_breaker: Some(CircuitBreakerConfig::default()),
94 timeout: Some(TimeoutConfig::development()),
95 recovery: Some(RecoveryPolicy::development()),
96 health_check_interval: Duration::from_secs(30),
97 }
98 }
99
100 pub fn with_circuit_breaker(mut self, config: CircuitBreakerConfig) -> Self {
102 self.circuit_breaker = Some(config);
103 self
104 }
105
106 pub fn with_timeout(mut self, config: TimeoutConfig) -> Self {
108 self.timeout = Some(config);
109 self
110 }
111
112 pub fn with_recovery(mut self, policy: RecoveryPolicy) -> Self {
114 self.recovery = Some(policy);
115 self
116 }
117
118 pub fn with_health_check_interval(mut self, interval: Duration) -> Self {
120 self.health_check_interval = interval;
121 self
122 }
123}
124
125pub type ResilienceResult<T> = std::result::Result<T, ResilienceError>;
127
128#[derive(Debug, thiserror::Error)]
130pub enum ResilienceError {
131 #[error("Circuit breaker is open for {kernel_id}")]
133 CircuitOpen {
134 kernel_id: String,
136 },
137
138 #[error("Request timed out after {timeout:?}")]
140 Timeout {
141 timeout: Duration,
143 },
144
145 #[error("Deadline exceeded")]
147 DeadlineExceeded,
148
149 #[error("Max retries ({retries}) exceeded")]
151 MaxRetriesExceeded {
152 retries: u32,
154 },
155
156 #[error("Health check failed: {reason}")]
158 HealthCheckFailed {
159 reason: String,
161 },
162
163 #[error("Kernel error: {0}")]
165 KernelError(#[from] crate::error::KernelError),
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn test_default_config() {
174 let config = ResilienceConfig::default();
175 assert!(config.circuit_breaker.is_some());
176 assert!(config.timeout.is_some());
177 assert!(config.recovery.is_some());
178 }
179
180 #[test]
181 fn test_disabled_config() {
182 let config = ResilienceConfig::disabled();
183 assert!(config.circuit_breaker.is_none());
184 assert!(config.timeout.is_none());
185 assert!(config.recovery.is_none());
186 }
187
188 #[test]
189 fn test_production_config() {
190 let config = ResilienceConfig::production();
191 assert!(config.circuit_breaker.is_some());
192 assert!(config.timeout.is_some());
193 }
194}