# nobreak
A minimal circuit breaker library for Rust with both sync and async support.
## Usage
Async (enabled by default via the `tokio` feature):
```rust
let cb = nobreak::breaker();
let result = cb
.call_async(|| async {
do_something().await
})
.await
.map_err(|e| e.into_inner().unwrap())?;
```
Sync:
```rust
let cb = nobreak::breaker();
let result = cb
.call(|| {
do_something()
})
.map_err(|e| e.into_inner().unwrap())?;
```
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:
```toml
nobreak = { version = "0.1", default-features = false }
```
## Builder
For more control, use the builder:
```rust
use std::time::Duration;
let cb = nobreak::builder()
.with_failure_threshold(10)
.with_success_threshold(3)
.with_open_duration(Duration::from_secs(60))
.build();
cb.call_async(|| async {
do_something().await
})
.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`. After `open_duration` elapses, transitions to half-open.
- **Half-open** — calls pass through to test recovery. A failure reopens the circuit. Once `success_threshold` consecutive successes occur, the circuit closes.
Inspect the current state at any time:
```rust
## Error handling
`CircuitError<E>` has two variants:
- `Failed { error }` — the operation was executed but returned an error
- `Open` — 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`).