appcore_core/
lifecycle.rs1use crate::error::{RuntimeError, RuntimeResult};
14use parking_lot::Mutex;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum RuntimeLifecycleState {
21 Booting,
23 LoadingConfig,
25 CheckingSecurity,
27 OpeningStorage,
29 StartingApi,
31 Running,
33 Degraded,
35 Restricted,
37 ShuttingDown,
39 Stopped,
41}
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45pub enum RuntimeLifecycleEvent {
46 ConfigLoaded,
48 SecurityChecked,
50 StorageOpened,
52 ApiStarted,
54 DegradedDetected,
56 RestrictedDetected,
58 ShutdownRequested,
60 ShutdownCompleted,
62 RecoveryCompleted,
64}
65
66#[derive(Debug)]
68pub struct RuntimeLifecycle {
69 state: Mutex<RuntimeLifecycleState>,
70}
71
72impl Clone for RuntimeLifecycle {
73 fn clone(&self) -> Self {
74 let state = *self.state.lock();
75 Self {
76 state: Mutex::new(state),
77 }
78 }
79}
80
81const fn next_state(
82 state: RuntimeLifecycleState,
83 event: RuntimeLifecycleEvent,
84) -> Option<RuntimeLifecycleState> {
85 match (state, event) {
86 (RuntimeLifecycleState::Booting, RuntimeLifecycleEvent::ConfigLoaded) => {
87 Some(RuntimeLifecycleState::CheckingSecurity)
88 }
89 (RuntimeLifecycleState::CheckingSecurity, RuntimeLifecycleEvent::SecurityChecked) => {
90 Some(RuntimeLifecycleState::OpeningStorage)
91 }
92 (RuntimeLifecycleState::OpeningStorage, RuntimeLifecycleEvent::StorageOpened) => {
93 Some(RuntimeLifecycleState::StartingApi)
94 }
95 (RuntimeLifecycleState::StartingApi, RuntimeLifecycleEvent::ApiStarted) => {
96 Some(RuntimeLifecycleState::Running)
97 }
98 (RuntimeLifecycleState::Running, RuntimeLifecycleEvent::DegradedDetected) => {
99 Some(RuntimeLifecycleState::Degraded)
100 }
101 (RuntimeLifecycleState::Running, RuntimeLifecycleEvent::RestrictedDetected) => {
102 Some(RuntimeLifecycleState::Restricted)
103 }
104 (
105 RuntimeLifecycleState::Degraded | RuntimeLifecycleState::Restricted,
106 RuntimeLifecycleEvent::RecoveryCompleted,
107 ) => Some(RuntimeLifecycleState::Running),
108 (
109 RuntimeLifecycleState::Running
110 | RuntimeLifecycleState::Degraded
111 | RuntimeLifecycleState::Restricted,
112 RuntimeLifecycleEvent::ShutdownRequested,
113 ) => Some(RuntimeLifecycleState::ShuttingDown),
114 (RuntimeLifecycleState::ShuttingDown, RuntimeLifecycleEvent::ShutdownCompleted) => {
115 Some(RuntimeLifecycleState::Stopped)
116 }
117 _ => None,
118 }
119}
120
121impl RuntimeLifecycle {
122 pub fn new() -> Self {
124 Self {
125 state: Mutex::new(RuntimeLifecycleState::Booting),
126 }
127 }
128
129 pub fn current(&self) -> RuntimeLifecycleState {
131 *self.state.lock()
132 }
133
134 pub fn apply(&self, event: RuntimeLifecycleEvent) -> RuntimeResult<RuntimeLifecycleState> {
136 let mut state = self.state.lock();
137 let next = next_state(*state, event).ok_or(RuntimeError::InvalidStateTransition)?;
138 *state = next;
139 Ok(next)
140 }
141
142 pub fn is_running(&self) -> bool {
144 self.current() == RuntimeLifecycleState::Running
145 }
146
147 pub fn is_stopped(&self) -> bool {
149 self.current() == RuntimeLifecycleState::Stopped
150 }
151
152 pub fn is_restricted(&self) -> bool {
154 self.current() == RuntimeLifecycleState::Restricted
155 }
156}
157
158impl Default for RuntimeLifecycle {
159 fn default() -> Self {
160 Self::new()
161 }
162}
163
164#[cfg(test)]
165#[path = "lifecycle_tests.rs"]
166mod tests;