use std::time::Duration;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CircuitState {
Closed,
Open,
HalfOpen,
}
#[derive(Debug, Clone)]
pub struct CircuitBreakerConfig {
pub failure_threshold: u32,
pub success_threshold: u32,
pub timeout: Duration,
}
impl Default for CircuitBreakerConfig {
fn default() -> Self {
Self {
failure_threshold: 5,
success_threshold: 2,
timeout: Duration::from_secs(30),
}
}
}
pub struct CircuitBreaker {
config: CircuitBreakerConfig,
state: CircuitState,
failure_count: u32,
success_count: u32,
}
impl CircuitBreaker {
pub fn new(config: CircuitBreakerConfig) -> Self {
Self {
config,
state: CircuitState::Closed,
failure_count: 0,
success_count: 0,
}
}
pub fn state(&self) -> CircuitState {
self.state
}
pub fn record_success(&mut self) {
self.failure_count = 0;
if self.state == CircuitState::HalfOpen {
self.success_count += 1;
if self.success_count >= self.config.success_threshold {
self.state = CircuitState::Closed;
self.success_count = 0;
}
}
}
pub fn record_failure(&mut self) {
self.failure_count += 1;
self.success_count = 0;
if self.failure_count >= self.config.failure_threshold {
self.state = CircuitState::Open;
}
}
pub fn is_call_permitted(&self) -> bool {
self.state != CircuitState::Open
}
}