use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
pub enum RestartPolicy {
#[default]
Permanent,
Temporary,
Transient,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TerminationReason {
Normal,
Panic(String),
InboxClosed,
ParentShutdown,
}
impl RestartPolicy {
#[must_use]
pub const fn should_restart(&self, reason: &TerminationReason) -> bool {
if matches!(reason, TerminationReason::ParentShutdown) {
return false;
}
match self {
Self::Permanent => true,
Self::Temporary => false,
Self::Transient => !matches!(reason, TerminationReason::Normal),
}
}
}
impl std::fmt::Display for RestartPolicy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Permanent => write!(f, "permanent"),
Self::Temporary => write!(f, "temporary"),
Self::Transient => write!(f, "transient"),
}
}
}
impl std::fmt::Display for TerminationReason {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Normal => write!(f, "normal shutdown"),
Self::Panic(msg) => write!(f, "panic: {msg}"),
Self::InboxClosed => write!(f, "inbox closed"),
Self::ParentShutdown => write!(f, "parent shutdown"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn permanent_restarts_on_panic() {
let policy = RestartPolicy::Permanent;
assert!(policy.should_restart(&TerminationReason::Panic("test".to_string())));
}
#[test]
fn permanent_restarts_on_normal() {
let policy = RestartPolicy::Permanent;
assert!(policy.should_restart(&TerminationReason::Normal));
}
#[test]
fn permanent_does_not_restart_on_parent_shutdown() {
let policy = RestartPolicy::Permanent;
assert!(!policy.should_restart(&TerminationReason::ParentShutdown));
}
#[test]
fn temporary_never_restarts() {
let policy = RestartPolicy::Temporary;
assert!(!policy.should_restart(&TerminationReason::Normal));
assert!(!policy.should_restart(&TerminationReason::Panic("test".to_string())));
assert!(!policy.should_restart(&TerminationReason::InboxClosed));
assert!(!policy.should_restart(&TerminationReason::ParentShutdown));
}
#[test]
fn transient_restarts_on_panic() {
let policy = RestartPolicy::Transient;
assert!(policy.should_restart(&TerminationReason::Panic("test".to_string())));
}
#[test]
fn transient_restarts_on_inbox_closed() {
let policy = RestartPolicy::Transient;
assert!(policy.should_restart(&TerminationReason::InboxClosed));
}
#[test]
fn transient_does_not_restart_on_normal() {
let policy = RestartPolicy::Transient;
assert!(!policy.should_restart(&TerminationReason::Normal));
}
#[test]
fn transient_does_not_restart_on_parent_shutdown() {
let policy = RestartPolicy::Transient;
assert!(!policy.should_restart(&TerminationReason::ParentShutdown));
}
}