A CircuitBreaker detects failures and encapsulates the logic to prevent them from constantly recurring during maintenance or external system outages. You can use it to wrap functions that might fail. When the failure threshold is met, the circuit breaker enters an 'open' state and rejects subsequent calls with Error::Rejected until the backoff period expires.
By default, Config::new().build() provides a circuit breaker with a reasonable default backoff and failure accrual policy.
use rand::{thread_rng, Rng};
use failsafe::{Config, CircuitBreaker, Error};
// A function that sometimes fails.
fn dangerous_call() -> Result<(), ()> {
if thread_rng().gen_range(0..2) == 0 {
return Err(())
}
Ok(())
}
// Create a circuit breaker with default backoff and failure accrual policy.
let circuit_breaker = Config::new().build();
// Call the function in a loop. After some iterations, the circuit breaker
// will be in an open state and reject next calls.
for n in 0..100 {
match circuit_breaker.call(|| dangerous_call()) {
Err(Error::Inner(_)) => {
eprintln!("{}: fail", n);
},
Err(Error::Rejected) => {
eprintln!("{}: rejected", n);
break;
},
_ => {}
}
}