Skip to main content

adaptive_timeout/
lib.rs

1//! Adaptive timeout computation based on observed latency quantiles.
2//!
3//! A [`LatencyTracker`] records latencies per destination using sliding-window
4//! histograms. An [`AdaptiveTimeout`] queries the tracker for a high quantile,
5//! applies a safety factor and exponential backoff, and clamps the result
6//! between a configurable floor and ceiling.
7//!
8//! When insufficient data is available, falls back to pure exponential backoff.
9//!
10//! # Per-service tracking
11//!
12//! Create one [`LatencyTracker`] per service/operation type. This keeps each
13//! service's latency distribution independent.
14//!
15//! # Example
16//!
17//! ```rust
18//! use std::time::{Duration, Instant};
19//! use adaptive_timeout::{AdaptiveTimeout, LatencyTracker};
20//!
21//! let now = Instant::now();
22//! let mut tracker = LatencyTracker::<u32, Instant>::default();
23//! let timeout = AdaptiveTimeout::default();
24//!
25//! // No data yet — falls back to exponential backoff.
26//! let t = timeout.select_timeout(&mut tracker, &[1u32], 1, now);
27//! assert_eq!(t, Duration::from_millis(250));
28//!
29//! // Record some latency observations.
30//! for _ in 0..100 {
31//!     tracker.record_latency(&1u32, Duration::from_millis(50), now);
32//! }
33//!
34//! // Now the timeout adapts to observed latencies.
35//! let t = timeout.select_timeout(&mut tracker, &[1u32], 1, now);
36//! assert!(t >= Duration::from_millis(50), "timeout should reflect observed latency");
37//! ```
38
39pub mod clock;
40mod config;
41mod histogram;
42mod parse;
43#[cfg(feature = "sync")]
44mod sync_tracker;
45mod timeout;
46mod tracker;
47
48pub use clock::Instant;
49pub use config::{MillisNonZero, TimeoutConfig, TrackerConfig};
50pub use parse::{BackoffInterval, ParseError};
51#[cfg(feature = "sync")]
52pub use sync_tracker::SyncLatencyTracker;
53pub use timeout::AdaptiveTimeout;
54pub use tracker::DEFAULT_SUB_WINDOWS;
55pub use tracker::LatencyTracker;