use std::num::NonZeroU32;
use std::time::Duration;
use crate::BackoffInterval;
pub type MillisNonZero = NonZeroU32;
#[inline]
pub(crate) const fn millis(ms: u32) -> MillisNonZero {
match NonZeroU32::new(ms) {
Some(v) => v,
None => panic!("millis value must be non-zero"),
}
}
pub(crate) const SIGNIFICANT_VALUE_DIGITS: u8 = 2;
#[derive(Debug, Clone, Copy)]
pub struct TrackerConfig {
pub window_ms: NonZeroU32,
pub min_samples: u32,
pub max_trackable_latency_ms: u32,
}
impl TrackerConfig {
#[inline]
pub fn window(&self) -> Duration {
Duration::from_millis(self.window_ms.get() as u64)
}
}
impl Default for TrackerConfig {
fn default() -> Self {
Self {
window_ms: millis(60_000),
min_samples: 3,
max_trackable_latency_ms: 60_000,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct TimeoutConfig {
pub backoff: BackoffInterval,
pub quantile: f64,
pub safety_factor: f64,
}
impl TimeoutConfig {
#[inline]
pub fn min_timeout(&self) -> Duration {
Duration::from_millis(self.backoff.min_ms.get() as u64)
}
#[inline]
pub fn max_timeout(&self) -> Duration {
Duration::from_millis(self.backoff.max_ms.get() as u64)
}
}
impl Default for TimeoutConfig {
fn default() -> Self {
Self {
backoff: BackoffInterval::default(),
quantile: 0.9999,
safety_factor: 2.0,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::mem;
#[test]
fn timeout_config_is_compact() {
assert_eq!(mem::size_of::<TimeoutConfig>(), 24);
}
#[test]
fn tracker_config_is_compact() {
assert!(mem::size_of::<TrackerConfig>() <= 12);
}
#[test]
fn millis_helper() {
let m = millis(42);
assert_eq!(m.get(), 42);
}
#[test]
#[should_panic(expected = "non-zero")]
fn millis_zero_panics() {
let _ = millis(0);
}
#[test]
fn timeout_config_conversions() {
let cfg = TimeoutConfig::default();
assert_eq!(cfg.min_timeout(), Duration::from_millis(250));
assert_eq!(cfg.max_timeout(), Duration::from_millis(60_000));
}
#[test]
fn tracker_config_window_conversion() {
let cfg = TrackerConfig::default();
assert_eq!(cfg.window(), Duration::from_secs(60));
}
}