mm1_sup/common/
restart_intensity.rs

1use std::fmt;
2use std::time::Duration;
3
4#[derive(Debug, thiserror::Error)]
5#[error("max restart intensity reached")]
6pub struct MaxRestartIntensityReached;
7
8#[derive(Debug, Clone, Copy)]
9pub struct RestartIntensity {
10    pub max_restarts: usize,
11    pub within:       Duration,
12}
13
14#[derive(Default, Debug)]
15pub struct RestartStats(Vec<tokio::time::Instant>);
16
17impl RestartIntensity {
18    pub fn new_stats(&self) -> RestartStats {
19        RestartStats(Vec::with_capacity(self.max_restarts + 1))
20    }
21
22    pub fn report_exit(
23        &self,
24        stats: &mut RestartStats,
25        now: tokio::time::Instant,
26    ) -> Result<(), MaxRestartIntensityReached> {
27        let t_cutoff = now.checked_sub(self.within).unwrap_or(now);
28        stats.0.retain(|t| *t >= t_cutoff);
29        stats.0.push(now);
30
31        if stats.0.len() > self.max_restarts {
32            Err(MaxRestartIntensityReached)
33        } else {
34            Ok(())
35        }
36    }
37}
38
39impl Default for RestartIntensity {
40    fn default() -> Self {
41        Self {
42            max_restarts: 0,
43            within:       Duration::MAX,
44        }
45    }
46}
47
48impl fmt::Display for RestartIntensity
49where
50    Self: fmt::Debug,
51{
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        write!(f, "{self:?}")
54    }
55}