nobreak
A minimal circuit breaker library for Rust with both sync and async support.
Usage
Async (enabled by default via the tokio feature):
let cb = breaker;
let result = cb
.call_async
.await
.map_err?;
Sync:
let cb = breaker;
let result = cb
.call
.map_err?;
Both use sensible defaults: 5 failure threshold, 2 success threshold for half-open recovery, and a 30s open duration.
The circuit breaker tracks consecutive failures. Once the failure threshold is reached, the circuit opens and subsequent calls are rejected immediately with CircuitError::Open without executing the function. After the open duration elapses, the circuit transitions to half-open and allows calls through again. If enough consecutive successes occur, the circuit closes. If a call fails in half-open, the circuit reopens.
Features
The tokio feature is enabled by default, providing call_async. To use only the sync API:
= { = "0.1", = false }
Builder
For more control, use the builder:
use Duration;
let cb = builder
.with_failure_threshold
.with_success_threshold
.with_open_duration
.build;
cb.call_async
.await?;
Configuration
with_failure_threshold(n)— number of consecutive failures before the circuit opens (default: 5)with_success_threshold(n)— number of consecutive successes in half-open state before the circuit closes (default: 2)with_open_duration(dur)— how long the circuit stays open before transitioning to half-open (default: 30s)
Circuit states
- Closed — normal operation, calls pass through. Consecutive failures are tracked; a success resets the count.
- Open — calls are rejected immediately with
CircuitError::Open. Afteropen_durationelapses, transitions to half-open. - Half-open — calls pass through to test recovery. A failure reopens the circuit. Once
success_thresholdconsecutive successes occur, the circuit closes.
Inspect the current state at any time:
let state = cb.state; // CircuitState::Closed | Open | HalfOpen
Error handling
CircuitError<E> has two variants:
Failed { error }— the operation was executed but returned an errorOpen— the circuit is open; the operation was not executed
Call .into_inner() to extract the underlying error as an Option<E> (returns None for Open).