tower_resilience_outlier/lib.rs
1//! Outlier detection middleware for Tower services.
2//!
3//! Outlier detection tracks per-instance health on live traffic and ejects
4//! unhealthy instances from a fleet. This is complementary to circuit breaker:
5//!
6//! | | Circuit Breaker | Outlier Detection |
7//! |---|---|---|
8//! | Trigger | Failure *rate* over sliding window | *Consecutive* errors |
9//! | Scope | Per-service, isolated | Fleet-aware (`max_ejection_percent`) |
10//! | Detection speed | Needs `minimum_calls` before evaluating | Catches hard-down immediately |
11//! | Recovery | Half-open state with probe calls | Time-based automatic recovery |
12//!
13//! # Quick Start
14//!
15//! ```rust
16//! use tower_resilience_outlier::{OutlierDetectionLayer, OutlierDetector};
17//! use tower::{ServiceBuilder, service_fn};
18//! use std::time::Duration;
19//!
20//! // Create a shared detector for the fleet
21//! let detector = OutlierDetector::new()
22//! .max_ejection_percent(50)
23//! .base_ejection_duration(Duration::from_secs(30));
24//!
25//! // Register instances
26//! detector.register("backend-1", 5); // eject after 5 consecutive errors
27//! detector.register("backend-2", 5);
28//!
29//! // Create per-instance layers sharing the same detector
30//! let layer1 = OutlierDetectionLayer::builder()
31//! .detector(detector.clone())
32//! .instance_name("backend-1")
33//! .build();
34//!
35//! let layer2 = OutlierDetectionLayer::builder()
36//! .detector(detector.clone())
37//! .instance_name("backend-2")
38//! .build();
39//!
40//! // Apply to services
41//! let svc1 = ServiceBuilder::new()
42//! .layer(layer1)
43//! .service(service_fn(|req: String| async move { Ok::<_, std::io::Error>(req) }));
44//! ```
45//!
46//! # Backpressure vs Error Mode
47//!
48//! By default, ejected instances return `Pending` from `poll_ready()`, which
49//! causes Tower load balancers to route around them. For cases where you want
50//! an explicit error, use `.error_on_ejection()`:
51//!
52//! ```rust
53//! # use tower_resilience_outlier::{OutlierDetectionLayer, OutlierDetector};
54//! # let detector = OutlierDetector::new();
55//! # detector.register("backend-1", 5);
56//! let layer = OutlierDetectionLayer::builder()
57//! .detector(detector)
58//! .instance_name("backend-1")
59//! .error_on_ejection()
60//! .build();
61//! ```
62
63/// Configuration types for outlier detection.
64pub mod config;
65/// Shared fleet-level outlier detector state.
66pub mod detector;
67/// Error types for outlier detection.
68pub mod error;
69/// Event types emitted by outlier detection.
70pub mod events;
71/// Tower `Layer` implementation for outlier detection.
72pub mod layer;
73/// Tower `Service` implementation for outlier detection.
74pub mod service;
75/// Ejection strategies (e.g., consecutive errors).
76pub mod strategy;
77
78pub use config::{OutlierDetectionConfig, OutlierDetectionConfigBuilder};
79pub use detector::OutlierDetector;
80pub use error::{OutlierDetectionError, OutlierDetectionServiceError};
81pub use events::OutlierDetectionEvent;
82pub use layer::OutlierDetectionLayer;
83pub use service::OutlierDetectionService;
84pub use strategy::{ConsecutiveErrors, EjectionStrategy};