use std::{num::NonZeroU64, time::Duration};
use tracing::warn;
use crate::ActorStatus;
#[derive(Debug, Clone, PartialEq)]
pub struct RestartPolicy {
pub(crate) mode: RestartMode,
}
impl Default for RestartPolicy {
fn default() -> Self {
Self::never()
}
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum RestartMode {
Always(RestartParams),
OnFailure(RestartParams),
Never,
}
impl RestartPolicy {
pub fn always(restart_params: RestartParams) -> Self {
Self {
mode: RestartMode::Always(restart_params),
}
}
pub fn on_failure(restart_params: RestartParams) -> Self {
Self {
mode: RestartMode::OnFailure(restart_params),
}
}
pub fn never() -> Self {
Self {
mode: RestartMode::Never,
}
}
pub(crate) fn restarting_allowed(&self, status: &ActorStatus) -> bool {
match &self.mode {
RestartMode::Always(_) => true,
RestartMode::OnFailure(_) => status.kind().is_failed(),
_ => false,
}
}
pub(crate) fn restart_params(&self) -> Option<RestartParams> {
match &self.mode {
RestartMode::Always(params) | RestartMode::OnFailure(params) => Some(*params),
_ => None,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct RestartParams {
pub(crate) min_backoff: Duration,
pub(crate) max_backoff: Duration,
pub(crate) auto_reset: Duration,
pub(crate) max_retries: NonZeroU64,
pub(crate) factor: f64,
}
impl RestartParams {
pub fn new(min_backoff: Duration, max_backoff: Duration) -> Self {
RestartParams {
min_backoff,
max_backoff: min_backoff.max(max_backoff),
auto_reset: min_backoff,
max_retries: NonZeroU64::MAX,
factor: 2.0,
}
}
pub fn auto_reset(self, auto_reset: impl Into<Option<Duration>>) -> Self {
Self {
auto_reset: auto_reset.into().unwrap_or(self.auto_reset),
..self
}
}
pub fn factor(self, factor: impl Into<Option<f64>>) -> Self {
let factor = factor.into().unwrap_or(self.factor);
let factor = if !factor.is_finite() || factor.is_sign_negative() {
warn!("factor should be a finite value and should not be negative");
0.0
} else {
factor
};
Self { factor, ..self }
}
pub fn max_retries(self, max_retries: impl Into<Option<NonZeroU64>>) -> Self {
Self {
max_retries: max_retries.into().unwrap_or(self.max_retries),
..self
}
}
}