use crate::{config::*, RequestReport};
use std::time::Duration;
pub trait Timeout: Send + 'static {
fn get_timeout(&self, size: usize, retries: usize) -> Duration;
fn update(&mut self, _: &RequestReport);
fn get_estimate(&self) -> f64;
}
pub struct TimeoutState {
seconds_per_unit_estimate: f64,
cfg: AlgorithmConfig,
specific: SpecificTimings,
}
impl TimeoutState {
pub fn new(cfg: AlgorithmConfig, specific: SpecificTimings) -> TimeoutState {
TimeoutState {
seconds_per_unit_estimate: specific.seconds_per_unit,
cfg,
specific,
}
}
}
impl Timeout for TimeoutState {
fn get_estimate(&self) -> f64 {
self.seconds_per_unit_estimate
}
fn get_timeout(&self, size: usize, retries: usize) -> Duration {
let backoff = self.cfg.backoff.powi(retries as i32);
let time_estimate = (size as f64) * self.seconds_per_unit_estimate * backoff;
Duration::from_secs_f64(
self.cfg.base_timeout * backoff + self.cfg.timeout_fraction * time_estimate,
)
}
fn update(&mut self, result: &RequestReport) {
if result.size > self.specific.minimum_units_for_estimation {
let target = result.success_time.as_secs_f64() / (result.size as f64);
self.seconds_per_unit_estimate = self.cfg.avg_power * self.seconds_per_unit_estimate
+ (1.0 - self.cfg.avg_power) * target;
}
}
}