7 releases (3 stable)

1.2.0 Aug 22, 2022
1.1.0 Jul 17, 2021
1.0.0 Aug 17, 2020
0.3.1 Jun 10, 2019
0.1.0 Sep 3, 2018

#231 in Asynchronous

Download history 3546/week @ 2023-10-20 3812/week @ 2023-10-27 3547/week @ 2023-11-03 3296/week @ 2023-11-10 3806/week @ 2023-11-17 2826/week @ 2023-11-24 3542/week @ 2023-12-01 3392/week @ 2023-12-08 2977/week @ 2023-12-15 1454/week @ 2023-12-22 2712/week @ 2023-12-29 3544/week @ 2024-01-05 3083/week @ 2024-01-12 1874/week @ 2024-01-19 1734/week @ 2024-01-26 1913/week @ 2024-02-02

9,249 downloads per month
Used in 7 crates (4 directly)

MIT license

71KB
1.5K SLoC

Failsafe

Сrate Вocumentation CircleCI Appveyor

A circuit breaker implementation which used to detect failures and encapsulates the logic of preventing a failure from constantly recurring, during maintenance, temporary external system failure or unexpected system difficulties.

Features

  • Working with both Fn() -> Result and Future (optional via default futures-support feature).
  • Backoff strategies: constant, exponential, equal_jittered, full_jittered
  • Failure detection policies: consecutive_failures, success_rate_over_time_window
  • Minimum rust version: 1.49

Usage

Add this to your Cargo.toml:

failsafe = "1.2.0"

Example

Using default backoff strategy and failure accrual policy.

use failsafe::{Config, CircuitBreaker, Error};

// A function that sometimes failed.
fn dangerous_call() -> Result<(), ()> {
  if thread_rng().gen_range(0, 2) == 0 {
    return Err(())
  }
  Ok(())
}

// Create a circuit breaker which configured by reasonable 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 a 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;
    },
    _ => {}
  }
}

Or configure custom backoff and policy:

use std::time::Duration;
use failsafe::{backoff, failure_policy, CircuitBreaker};

// Create an exponential growth backoff which starts from 10s and ends with 60s.
let backoff = backoff::exponential(Duration::from_secs(10), Duration::from_secs(60));

// Create a policy which failed when three consecutive failures were made.
let policy = failure_policy::consecutive_failures(3, backoff);

// Creates a circuit breaker with given policy.
let circuit_breaker = Config::new()
  .failure_policy(policy)
  .build();

Dependencies

~0.6–6.5MB
~19K SLoC