Skip to main content

muster/application/
process_lifecycle.rs

1use crate::domain::{
2    process::{ExitIntent, ProcessState},
3    pty::ExitOutcome,
4};
5
6/// Next lifecycle action after a managed child exits.
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum ExitDecision {
9    /// Remove a pane retired by configuration reconciliation.
10    Retire,
11    /// Keep the pane stopped after an explicit user stop.
12    Stop,
13    /// Respawn immediately after a requested restart.
14    RestartNow,
15    /// Schedule a policy restart after backoff.
16    RestartLater,
17    /// Keep the pane stopped with the terminal exit disposition.
18    Settle(ProcessState),
19}
20
21/// Pure process lifecycle policy used by the TUI runtime.
22pub struct ProcessLifecycle;
23
24impl ProcessLifecycle {
25    /// Chooses the post-exit action from explicit intent and restart policy.
26    pub fn after_exit(
27        intent: ExitIntent,
28        retired_by_config: bool,
29        should_restart: bool,
30        outcome: ExitOutcome,
31    ) -> ExitDecision {
32        if retired_by_config {
33            return ExitDecision::Retire;
34        }
35        match intent {
36            ExitIntent::StopRetryable | ExitIntent::StopInFlight => ExitDecision::Stop,
37            ExitIntent::RestartRetryable | ExitIntent::RestartInFlight => ExitDecision::RestartNow,
38            ExitIntent::FollowPolicy if should_restart => ExitDecision::RestartLater,
39            ExitIntent::FollowPolicy => ExitDecision::Settle(exit_state(outcome)),
40        }
41    }
42}
43
44/// Maps an OS process outcome to the state rendered for an inactive pane.
45fn exit_state(outcome: ExitOutcome) -> ProcessState {
46    match outcome {
47        ExitOutcome::Succeeded => ProcessState::Exited,
48        ExitOutcome::Failed => ProcessState::Crashed,
49    }
50}