1use crate::config::*;
4use crate::RequestReport;
5use std::time::Duration;
6pub trait Timeout: Send + 'static {
7 fn get_timeout(&self, size: usize, retries: usize) -> Duration;
9 fn update(&mut self, _: &RequestReport);
11 fn get_estimate(&self) -> f64;
13}
14pub struct TimeoutState {
17 seconds_per_unit_estimate: f64,
18 cfg: AlgorithmConfig,
19 specific: SpecificTimings,
20}
21impl TimeoutState {
22 pub fn new(cfg: AlgorithmConfig, specific: SpecificTimings) -> TimeoutState {
23 TimeoutState {
24 seconds_per_unit_estimate: specific.seconds_per_unit,
25 cfg,
26 specific,
27 }
28 }
29}
30impl Timeout for TimeoutState {
31 fn get_estimate(&self) -> f64 {
33 self.seconds_per_unit_estimate
34 }
35 fn get_timeout(&self, size: usize, retries: usize) -> Duration {
36 let backoff = self.cfg.backoff.powi(retries as i32);
37 let time_estimate = (size as f64) * self.seconds_per_unit_estimate * backoff;
38 Duration::from_secs_f64(
39 self.cfg.base_timeout * backoff + self.cfg.timeout_fraction * time_estimate,
40 )
41 }
42 fn update(&mut self, result: &RequestReport) {
43 if result.size > self.specific.minimum_units_for_estimation {
44 let target = result.success_time.as_secs_f64() / (result.size as f64);
45 self.seconds_per_unit_estimate = self.cfg.avg_power * self.seconds_per_unit_estimate
46 + (1.0 - self.cfg.avg_power) * target;
47 }
48 }
49}