mm1_sup/common/
restart_intensity.rs1use 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}