muster/domain/process/
exit_intent.rs1#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
3pub enum ExitIntent {
4 #[default]
6 FollowPolicy,
7 StopRetryable,
10 StopInFlight,
12 RestartRetryable,
15 RestartInFlight,
17}
18
19impl ExitIntent {
20 pub fn request_stop(self) -> Self {
22 Self::StopRetryable
23 }
24
25 pub fn stop_delivered(self) -> Self {
27 if self.is_stop() {
28 Self::StopInFlight
29 } else {
30 self
31 }
32 }
33
34 pub fn stop_delivery_failed(self) -> Self {
37 if self.is_stop() {
38 Self::StopRetryable
39 } else {
40 self
41 }
42 }
43
44 pub fn request_restart(self) -> Self {
46 Self::RestartRetryable
47 }
48
49 pub fn restart_delivered(self) -> Self {
51 if self.is_restart() {
52 Self::RestartInFlight
53 } else {
54 self
55 }
56 }
57
58 pub fn restart_delivery_failed(self) -> Self {
61 if self.is_restart() {
62 Self::RestartRetryable
63 } else {
64 self
65 }
66 }
67
68 pub fn accepts_stop_request(self) -> bool {
70 self != Self::StopInFlight
71 }
72
73 pub fn accepts_restart_request(self) -> bool {
75 self != Self::RestartInFlight
76 }
77
78 pub fn is_stop(self) -> bool {
80 matches!(self, Self::StopRetryable | Self::StopInFlight)
81 }
82
83 pub fn is_restart(self) -> bool {
85 matches!(self, Self::RestartRetryable | Self::RestartInFlight)
86 }
87
88 pub fn force_stop_delivery_failed(self) -> Self {
91 match self {
92 Self::StopInFlight => Self::StopRetryable,
93 Self::RestartInFlight => Self::RestartRetryable,
94 _ => self,
95 }
96 }
97
98 pub fn awaits_force_stop(self) -> bool {
100 matches!(self, Self::StopInFlight | Self::RestartInFlight)
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn failed_delivery_preserves_stop_intent_and_allows_retry() {
110 let intent = ExitIntent::default().request_stop().stop_delivery_failed();
111
112 assert!(intent.is_stop());
113 assert!(intent.accepts_stop_request());
114 assert!(!intent.awaits_force_stop());
115 }
116
117 #[test]
118 fn successful_delivery_suppresses_duplicate_stop_requests() {
119 let intent = ExitIntent::default().request_stop().stop_delivered();
120
121 assert!(intent.is_stop());
122 assert!(!intent.accepts_stop_request());
123 assert!(intent.awaits_force_stop());
124 }
125
126 #[test]
127 fn restart_replaces_a_prior_stop_intent() {
128 let intent = ExitIntent::default()
129 .request_stop()
130 .stop_delivered()
131 .request_restart();
132
133 assert_eq!(intent, ExitIntent::RestartRetryable);
134 assert!(!intent.is_stop());
135 assert!(intent.is_restart());
136 }
137
138 #[test]
140 fn successful_restart_delivery_awaits_force_stop() {
141 let intent = ExitIntent::default().request_restart().restart_delivered();
142
143 assert_eq!(intent, ExitIntent::RestartInFlight);
144 assert!(!intent.accepts_restart_request());
145 assert!(intent.awaits_force_stop());
146 }
147
148 #[test]
150 fn failed_restart_escalation_remains_retryable() {
151 let intent = ExitIntent::RestartInFlight.force_stop_delivery_failed();
152
153 assert_eq!(intent, ExitIntent::RestartRetryable);
154 assert!(intent.accepts_restart_request());
155 }
156}