Expand description
§Nine Lives 🐱
Resilience patterns for Rust: retry policies, circuit breakers, bulkheads, and timeouts.
§Features
- Retry policies with backoff strategies (constant, linear, exponential)
- Circuit breakers with half-open state recovery
- Bulkheads for concurrency limiting and resource isolation
- Timeout policies integrated with tokio
- Policy composition via tower-native layers and algebraic operators
- Lock-free implementations using atomics
§Quick Start
§Basic Usage - Single Layer
use ninelives::prelude::*;
use std::time::Duration;
use tower::{Service, ServiceBuilder};
// Create a simple service
let mut svc = ServiceBuilder::new()
.layer(TimeoutLayer::new(Duration::from_secs(1))?)
.service_fn(|req: &'static str| async move {
Ok::<_, std::io::Error>(req)
});
let response = svc.call("hello").await?;
assert_eq!(response, "hello");§Algebraic Composition - The Power of Policy
Compose layers using intuitive operators:
use ninelives::prelude::*;
use std::time::Duration;
use tower::{Service, ServiceBuilder};
// Define resilience strategy using algebra
// Try fast timeout, fallback to longer timeout
let fast = Policy(TimeoutLayer::new(Duration::from_millis(100))?);
let slow = Policy(TimeoutLayer::new(Duration::from_secs(5))?);
let policy = fast | slow; // Fallback operator
// Apply to any service
let mut svc = ServiceBuilder::new()
.layer(policy)
.service_fn(|req: &'static str| async move {
Ok::<_, std::io::Error>(req)
});
let response = svc.call("hello").await?;§Complex Composition
Combine multiple strategies with precedence:
use ninelives::prelude::*;
use std::time::Duration;
// Aggressive: fast timeout only
let aggressive = Policy(TimeoutLayer::new(Duration::from_millis(50))?);
// Defensive: nested timeouts for resilience
let defensive = Policy(TimeoutLayer::new(Duration::from_secs(10))?)
+ Policy(TimeoutLayer::new(Duration::from_secs(5))?);
// Try aggressive first, fall back to defensive
// Operator precedence: + binds tighter than |
let _policy = aggressive | defensive;
// This creates: Policy(Timeout50ms) | (Policy(Timeout10s) + Policy(Timeout5s))§Algebraic Operators
Policy(A) + Policy(B)- Sequential composition:AwrapsBPolicy(A) | Policy(B)- Fallback: tryA, fall back toBon errorPolicy(A) & Policy(B)- Fork-join: try both concurrently, return first success
Precedence: & > + > | (like * > + > bitwise-or in math)
Example: A | B + C & D is parsed as A | (B + (C & D))
§Available Layers
TimeoutLayer- Enforce time limits on operationsRetryLayer- Retry failed operations with backoffCircuitBreakerLayer- Prevent cascading failuresBulkheadLayer- Limit concurrent requests
For more examples, see the algebra module documentation.
Modules§
- prelude
- Convenient re-exports for common Nine Lives types.
- telemetry
- Telemetry and observability for Nine Lives policies.
Structs§
- Backoff
- Backoff strategy wrapper preserving the existing API while delegating to concrete strategies.
- Bulkhead
Layer - Tower-native bulkhead layer with optional telemetry.
- Bulkhead
Policy - Concurrency-limiting bulkhead. Clones share the same underlying semaphore via
Arc, so they observe and affect the same in-flight count.max_concurrentis the configured permit ceiling. - Circuit
Breaker Config - Validated configuration for the circuit breaker.
- Circuit
Breaker Layer - Tower-native circuit breaker layer with optional telemetry.
- Combined
Layer - Sequential composition layer that applies
innerfirst, thenouter. - Constant
Backoff - Constant backoff strategy.
- Exponential
Backoff - Exponential backoff strategy.
- Fallback
Layer - Fallback composition layer that tries
primary, falling back tosecondaryon error. - Fallback
Service - Tower service that executes primary, falling back to secondary on error.
- Fork
Join Layer - Fork-join composition layer that tries both
leftandrightconcurrently. - Fork
Join Service - Tower service that races two services concurrently, returning the first success.
- Instant
Sleeper - Test sleeper that doesn’t actually sleep.
- Linear
Backoff - Linear backoff strategy.
- Monotonic
Clock - Monotonic clock backed by
Instant::now(). - Policy
- Opt-in wrapper enabling algebraic composition of tower layers.
- Retry
Layer - Tower-native retry layer with optional telemetry.
- Retry
Policy - Retry policy combining backoff, jitter, predicate, and sleeper.
- Retry
Policy Builder - Builder for
RetryPolicy. - Retry
Service - Retry service produced by
RetryLayer. - Timeout
Layer - Tower-native timeout layer with optional telemetry.
- Timeout
Policy - Policy that enforces a maximum duration on async operations.
- Tokio
Sleeper - Production sleeper using tokio runtime.
- Tracking
Sleeper - Test sleeper that tracks all sleep calls. Clones share the same recorded history via
Arc, so any clone observing or pushing sleeps sees the combined timeline.
Enums§
- Backoff
Error - Errors returned by backoff configuration.
- Build
Error - Errors produced while building a retry policy.
- Bulkhead
Error - Errors produced while configuring a bulkhead (e.g., invalid permit counts).
- Circuit
Breaker Error - Errors produced when validating breaker configuration.
- Circuit
State - Circuit breaker state machine.
- Jitter
- Jitter strategy for randomizing retry delays
- Resilience
Error - Unified error type for all resilience policies
- Timeout
Error - Errors returned when configuring timeouts.
Constants§
- MAX_
BACKOFF - Maximum delay used when calculations overflow (1 day).
- MAX_
TIMEOUT - Maximum allowed timeout duration (30 days) to avoid runaway timers while permitting long jobs.
Intended to guard accidental timeouts of
u64::MAX; override viaTimeoutPolicy::new_with_maxwhen longer horizons are required.
Traits§
- Backoff
Strategy - Trait implemented by all backoff strategies.
- Clock
- Thread-safe time source abstraction.
- Sleeper
- Contract for sleeping/waiting.