Skip to main content

reliability_toolkit/
lib.rs

1//! # reliability-toolkit
2//!
3//! Async reliability primitives for Tokio-based Rust services. The crate is
4//! deliberately small: each primitive is independent, composable, and avoids
5//! pulling in unrelated dependencies.
6//!
7//! ## Primitives
8//!
9//! - [`RateLimiter`] — token-bucket rate limiter with configurable burst.
10//! - [`CircuitBreaker`] — closed → open → half-open with failure-rate trip and cool-down.
11//! - [`Retry`] — exponential backoff with full jitter and per-error predicates.
12//! - [`Bulkhead`] — semaphore-backed concurrency cap.
13//!
14//! ## Composition
15//!
16//! Each primitive exposes an `execute()` (or `run()` / `acquire()`) that wraps
17//! a user-supplied future. They are designed so the typical layering pattern —
18//! `Retry(CircuitBreaker(Bulkhead(RateLimit(call))))` — falls out naturally.
19//!
20//! ```no_run
21//! use std::time::Duration;
22//! use reliability_toolkit::{RateLimiter, CircuitBreaker, Retry, Bulkhead, RetryConfig};
23//!
24//! # async fn outer() -> Result<(), Box<dyn std::error::Error>> {
25//! let limiter = RateLimiter::new(100.0, 100);            // 100 rps, burst 100
26//! let breaker = CircuitBreaker::builder()
27//!     .failure_threshold(5)
28//!     .cool_down(Duration::from_secs(10))
29//!     .build();
30//! let retry = Retry::new(RetryConfig::default());
31//! let pool = Bulkhead::new(20);
32//!
33//! let result: Result<(), std::io::Error> = retry
34//!     .run(|| async {
35//!         limiter.acquire().await;
36//!         let _permit = pool
37//!             .acquire()
38//!             .await
39//!             .map_err(std::io::Error::other)?;
40//!         match breaker.call(async { Ok::<_, std::io::Error>(()) }).await {
41//!             Ok(inner) => inner,
42//!             Err(open) => Err(std::io::Error::other(open.to_string())),
43//!         }
44//!     })
45//!     .await;
46//! # let _ = result;
47//! # Ok(()) }
48//! ```
49
50#![warn(missing_docs)]
51#![warn(rust_2018_idioms)]
52#![warn(clippy::pedantic)]
53#![allow(clippy::module_name_repetitions)]
54#![allow(clippy::missing_errors_doc)]
55#![allow(clippy::missing_panics_doc)]
56#![allow(clippy::must_use_candidate)]
57#![allow(clippy::cast_possible_truncation)]
58#![allow(clippy::cast_precision_loss)]
59#![allow(clippy::cast_sign_loss)]
60#![allow(clippy::doc_markdown)]
61
62pub mod bulkhead;
63pub mod circuit_breaker;
64pub mod error;
65pub mod rate_limiter;
66pub mod retry;
67
68/// Optional audit-stream-py producer. Gated behind the `audit-stream`
69/// Cargo feature so the core toolkit stays HTTP-free.
70#[cfg(feature = "audit-stream")]
71pub mod audit_stream;
72
73pub use bulkhead::{Bulkhead, BulkheadPermit};
74pub use circuit_breaker::{CircuitBreaker, CircuitBreakerBuilder, CircuitState};
75pub use error::ToolkitError;
76pub use rate_limiter::RateLimiter;
77pub use retry::{Retry, RetryConfig};
78
79#[cfg(feature = "audit-stream")]
80pub use audit_stream::AuditingBreaker;