1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use crate::{RequestConfig, RequestReport};
use std::time::Duration;
pub trait Timeout: Send + 'static {
fn get_timeout(&self, bytes: u64, retries: usize) -> Duration;
fn update(&mut self, _: &RequestReport);
fn get_estimate(&self) -> f64;
}
pub struct TimeoutState {
upload_speed_estimate: f64,
cfg: RequestConfig,
}
impl TimeoutState {
pub fn new(cfg: RequestConfig) -> TimeoutState {
TimeoutState {
upload_speed_estimate: cfg.expected_upload_speed,
cfg,
}
}
}
impl Timeout for TimeoutState {
fn get_estimate(&self) -> f64 {
self.upload_speed_estimate
}
fn get_timeout(&self, bytes: u64, retries: usize) -> Duration {
let backoff = self.cfg.backoff.powi(retries as i32);
if bytes > self.cfg.avg_min_bytes {
let megabytes = bytes as f64 / 1_000_000.0;
let time_estimate = megabytes / self.upload_speed_estimate * backoff;
Duration::from_secs_f64(
self.cfg.min_timeout * backoff + self.cfg.timeout_fraction * time_estimate,
)
} else {
Duration::from_secs_f64(self.cfg.min_timeout * backoff)
}
}
fn update(&mut self, result: &RequestReport) {
if result.bytes > self.cfg.avg_min_bytes {
let megabytes = result.bytes as f64 / 1_000_000.0;
let speed = megabytes / result.success_time.as_secs_f64();
self.upload_speed_estimate = self.cfg.avg_power * self.upload_speed_estimate
+ (1.0 - self.cfg.avg_power) * speed;
} else {
}
}
}