#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Timing {
pub timeout_ms: u64,
pub concurrency: usize,
pub retries: u32,
pub rate: Option<u32>,
}
pub const MAX_LEVEL: u8 = 5;
pub fn profile(level: u8) -> Timing {
match level {
0 => Timing {
timeout_ms: 5000,
concurrency: 1,
retries: 3,
rate: Some(10),
},
1 => Timing {
timeout_ms: 4000,
concurrency: 4,
retries: 2,
rate: Some(100),
},
2 => Timing {
timeout_ms: 3000,
concurrency: 16,
retries: 1,
rate: Some(1000),
},
3 => Timing {
timeout_ms: 2000,
concurrency: 256,
retries: 0,
rate: None,
},
4 => Timing {
timeout_ms: 1000,
concurrency: 512,
retries: 0,
rate: None,
},
_ => Timing {
timeout_ms: 500,
concurrency: 1024,
retries: 0,
rate: None,
},
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn levels_get_faster_as_they_rise() {
let profiles: Vec<Timing> = (0..=MAX_LEVEL).map(profile).collect();
for pair in profiles.windows(2) {
assert!(
pair[1].timeout_ms <= pair[0].timeout_ms,
"timeout should not increase with level"
);
assert!(
pair[1].concurrency >= pair[0].concurrency,
"concurrency should not decrease with level"
);
}
}
#[test]
fn paranoid_is_serial_and_rate_limited() {
let t0 = profile(0);
assert_eq!(t0.concurrency, 1);
assert!(t0.rate.is_some());
assert!(t0.retries > 0);
}
#[test]
fn insane_is_unlimited_and_widest() {
let t5 = profile(5);
assert_eq!(t5.rate, None);
assert_eq!(t5.concurrency, 1024);
}
#[test]
fn levels_above_max_clamp_to_insane() {
assert_eq!(profile(9), profile(MAX_LEVEL));
}
}