pub mod circuit_breaker;
pub mod health;
pub mod recovery;
pub mod timeout;
pub use circuit_breaker::{CircuitBreaker, CircuitBreakerConfig, CircuitState};
pub use health::{HealthCheck, HealthCheckResult, HealthProbe};
pub use recovery::{RecoveryPolicy, RecoveryStrategy, RetryConfig};
pub use timeout::{DeadlineContext, TimeoutConfig, TimeoutError};
pub use ringkernel_core::health as ring_health;
pub use ringkernel_core::rate_limiting as ring_rate_limiting;
pub use ringkernel_core::timeout as ring_timeout;
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResilienceConfig {
pub circuit_breaker: Option<CircuitBreakerConfig>,
pub timeout: Option<TimeoutConfig>,
pub recovery: Option<RecoveryPolicy>,
pub health_check_interval: Duration,
}
impl Default for ResilienceConfig {
fn default() -> Self {
Self {
circuit_breaker: Some(CircuitBreakerConfig::default()),
timeout: Some(TimeoutConfig::default()),
recovery: Some(RecoveryPolicy::default()),
health_check_interval: Duration::from_secs(10),
}
}
}
impl ResilienceConfig {
pub fn new() -> Self {
Self::default()
}
pub fn disabled() -> Self {
Self {
circuit_breaker: None,
timeout: None,
recovery: None,
health_check_interval: Duration::from_secs(60),
}
}
pub fn production() -> Self {
Self {
circuit_breaker: Some(CircuitBreakerConfig::production()),
timeout: Some(TimeoutConfig::production()),
recovery: Some(RecoveryPolicy::production()),
health_check_interval: Duration::from_secs(10),
}
}
pub fn development() -> Self {
Self {
circuit_breaker: Some(CircuitBreakerConfig::default()),
timeout: Some(TimeoutConfig::development()),
recovery: Some(RecoveryPolicy::development()),
health_check_interval: Duration::from_secs(30),
}
}
pub fn with_circuit_breaker(mut self, config: CircuitBreakerConfig) -> Self {
self.circuit_breaker = Some(config);
self
}
pub fn with_timeout(mut self, config: TimeoutConfig) -> Self {
self.timeout = Some(config);
self
}
pub fn with_recovery(mut self, policy: RecoveryPolicy) -> Self {
self.recovery = Some(policy);
self
}
pub fn with_health_check_interval(mut self, interval: Duration) -> Self {
self.health_check_interval = interval;
self
}
}
pub type ResilienceResult<T> = std::result::Result<T, ResilienceError>;
#[derive(Debug, thiserror::Error)]
pub enum ResilienceError {
#[error("Circuit breaker is open for {kernel_id}")]
CircuitOpen {
kernel_id: String,
},
#[error("Request timed out after {timeout:?}")]
Timeout {
timeout: Duration,
},
#[error("Deadline exceeded")]
DeadlineExceeded,
#[error("Max retries ({retries}) exceeded")]
MaxRetriesExceeded {
retries: u32,
},
#[error("Health check failed: {reason}")]
HealthCheckFailed {
reason: String,
},
#[error("Kernel error: {0}")]
KernelError(#[from] crate::error::KernelError),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = ResilienceConfig::default();
assert!(config.circuit_breaker.is_some());
assert!(config.timeout.is_some());
assert!(config.recovery.is_some());
}
#[test]
fn test_disabled_config() {
let config = ResilienceConfig::disabled();
assert!(config.circuit_breaker.is_none());
assert!(config.timeout.is_none());
assert!(config.recovery.is_none());
}
#[test]
fn test_production_config() {
let config = ResilienceConfig::production();
assert!(config.circuit_breaker.is_some());
assert!(config.timeout.is_some());
}
}