1use serde::{Deserialize, Serialize};
4use std::collections::VecDeque;
5use std::time::{Duration, Instant};
6
7use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
8
9#[derive(
11 Debug,
12 Default,
13 Clone,
14 Copy,
15 PartialEq,
16 Eq,
17 Serialize,
18 Deserialize,
19 Archive,
20 RkyvSerialize,
21 RkyvDeserialize,
22)]
23#[rkyv(derive(Debug))]
24pub enum RestartStrategy {
25 #[default]
27 OneForOne,
28 OneForAll,
30 RestForOne,
32}
33
34#[derive(
36 Debug,
37 Default,
38 Clone,
39 Copy,
40 PartialEq,
41 Eq,
42 Serialize,
43 Deserialize,
44 Archive,
45 RkyvSerialize,
46 RkyvDeserialize,
47)]
48#[rkyv(derive(Debug))]
49pub enum RestartPolicy {
50 #[default]
52 Permanent,
53 Temporary,
55 Transient,
57}
58
59#[derive(Debug, Clone, Copy)]
61pub struct RestartIntensity {
62 pub max_restarts: usize,
64 pub within_seconds: u64,
66}
67
68impl RestartIntensity {
69 #[inline]
79 #[must_use]
80 pub const fn new(max_restarts: usize, within_seconds: u64) -> Self {
81 Self {
82 max_restarts,
83 within_seconds,
84 }
85 }
86}
87
88impl Default for RestartIntensity {
89 fn default() -> Self {
90 Self::new(3, 5)
91 }
92}
93
94#[derive(Debug)]
96pub(crate) struct RestartTracker {
97 intensity: RestartIntensity,
98 restart_times: VecDeque<Instant>,
99}
100
101impl RestartTracker {
102 pub(crate) fn new(intensity: RestartIntensity) -> Self {
103 Self {
104 intensity,
105 restart_times: VecDeque::with_capacity(intensity.max_restarts.saturating_add(1)),
107 }
108 }
109
110 pub(crate) fn record_restart(&mut self) -> bool {
112 let now = Instant::now();
113 let cutoff = now
114 .checked_sub(Duration::from_secs(self.intensity.within_seconds))
115 .unwrap_or(now);
116
117 while let Some(&time) = self.restart_times.front() {
119 if time < cutoff {
120 self.restart_times.pop_front();
121 } else {
122 break;
123 }
124 }
125
126 self.restart_times.push_back(now);
127
128 self.restart_times.len() > self.intensity.max_restarts
130 }
131
132 #[allow(dead_code)]
133 pub(crate) fn reset(&mut self) {
134 self.restart_times.clear();
135 }
136}