Skip to main content

muster/domain/process/
restart.rs

1use serde::{Deserialize, Serialize};
2use strum::Display;
3
4use crate::domain::pty::ExitOutcome;
5
6/// How a process should be restarted when its child exits.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize, Display)]
8#[serde(rename_all = "snake_case")]
9#[strum(serialize_all = "snake_case")]
10pub enum RestartPolicy {
11    /// Never restart; a stopped process stays stopped.
12    #[default]
13    Never,
14    /// Restart only when the process exits with a failure status or signal.
15    OnFailure,
16    /// Always restart, whatever the exit status.
17    Always,
18}
19
20impl RestartPolicy {
21    /// Whether a process with this policy should be restarted after `outcome`.
22    pub fn should_restart(self, outcome: ExitOutcome) -> bool {
23        match self {
24            Self::Never => false,
25            Self::OnFailure => outcome == ExitOutcome::Failed,
26            Self::Always => true,
27        }
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34
35    #[test]
36    fn never_never_restarts() {
37        assert!(!RestartPolicy::Never.should_restart(ExitOutcome::Failed));
38        assert!(!RestartPolicy::Never.should_restart(ExitOutcome::Succeeded));
39    }
40
41    #[test]
42    fn on_failure_restarts_only_on_failure() {
43        assert!(RestartPolicy::OnFailure.should_restart(ExitOutcome::Failed));
44        assert!(!RestartPolicy::OnFailure.should_restart(ExitOutcome::Succeeded));
45    }
46
47    #[test]
48    fn always_restarts_regardless() {
49        assert!(RestartPolicy::Always.should_restart(ExitOutcome::Succeeded));
50        assert!(RestartPolicy::Always.should_restart(ExitOutcome::Failed));
51    }
52
53    #[test]
54    fn defaults_to_never() {
55        assert_eq!(RestartPolicy::default(), RestartPolicy::Never);
56    }
57}