use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
use std::time::{Duration, Instant};
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
#[derive(
Debug,
Default,
Clone,
Copy,
PartialEq,
Eq,
Serialize,
Deserialize,
Archive,
RkyvSerialize,
RkyvDeserialize,
)]
#[rkyv(derive(Debug))]
pub enum RestartStrategy {
#[default]
OneForOne,
OneForAll,
RestForOne,
}
#[derive(
Debug,
Default,
Clone,
Copy,
PartialEq,
Eq,
Serialize,
Deserialize,
Archive,
RkyvSerialize,
RkyvDeserialize,
)]
#[rkyv(derive(Debug))]
pub enum RestartPolicy {
#[default]
Permanent,
Temporary,
Transient,
}
#[derive(Debug, Clone, Copy)]
pub struct RestartIntensity {
pub max_restarts: usize,
pub within_seconds: u64,
}
impl RestartIntensity {
#[inline]
#[must_use]
pub const fn new(max_restarts: usize, within_seconds: u64) -> Self {
Self {
max_restarts,
within_seconds,
}
}
}
impl Default for RestartIntensity {
fn default() -> Self {
Self::new(3, 5)
}
}
#[derive(Debug)]
pub(crate) struct RestartTracker {
intensity: RestartIntensity,
restart_times: VecDeque<Instant>,
}
impl RestartTracker {
pub(crate) fn new(intensity: RestartIntensity) -> Self {
Self {
intensity,
restart_times: VecDeque::with_capacity(intensity.max_restarts.saturating_add(1)),
}
}
pub(crate) fn record_restart(&mut self) -> bool {
let now = Instant::now();
let cutoff = now
.checked_sub(Duration::from_secs(self.intensity.within_seconds))
.unwrap_or(now);
while let Some(&time) = self.restart_times.front() {
if time < cutoff {
self.restart_times.pop_front();
} else {
break;
}
}
self.restart_times.push_back(now);
self.restart_times.len() > self.intensity.max_restarts
}
#[allow(dead_code)]
pub(crate) fn reset(&mut self) {
self.restart_times.clear();
}
}