Skip to main content

appcore_core/
lifecycle.rs

1// =============================================================================
2//        #######
3//     ###       ###     F: lifecycle.rs
4//    ##   ## ##   ##    P: AppCore-Runtime
5//         ## ##
6//                       C: 2026/05/29 20:47:35 by dnettoRaw
7//    ##   ## ##   ##    U: 2026/06/07 12:00:00 by dnettoRaw
8//      ###########      S: 0.6.1
9// =============================================================================
10
11//! Bounded/thread-safe runtime lifecycle contract built on top of StateMachine.
12
13use crate::error::{RuntimeError, RuntimeResult};
14use crate::ids::{EventName, StateName};
15use crate::state::{StateMachine, StateTransition};
16use parking_lot::Mutex;
17
18// NOTA: Estados de lifecycle estendidos como checking-identity, discovering-peers, readonly e syncing
19// foram adiados para a versão v0.7 para manter a estabilidade do contrato de transições por enquanto.
20/// Stable process lifecycle state.
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum RuntimeLifecycleState {
23    /// Runtime process is booting.
24    Booting,
25    /// Runtime configuration is being loaded.
26    LoadingConfig,
27    /// Security configuration is being checked.
28    CheckingSecurity,
29    /// Storage boundaries are being opened.
30    OpeningStorage,
31    /// Runtime API boundaries are starting.
32    StartingApi,
33    /// Runtime is accepting declared work.
34    Running,
35    /// Runtime remains available with reduced guarantees.
36    Degraded,
37    /// Runtime accepts only explicitly permitted operations.
38    Restricted,
39    /// Runtime is performing graceful shutdown.
40    ShuttingDown,
41    /// Runtime has stopped.
42    Stopped,
43}
44
45/// Event accepted by the Runtime process lifecycle.
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub enum RuntimeLifecycleEvent {
48    /// Configuration loading completed.
49    ConfigLoaded,
50    /// Security checks completed.
51    SecurityChecked,
52    /// Storage initialization completed.
53    StorageOpened,
54    /// API startup completed.
55    ApiStarted,
56    /// A degradable failure was observed.
57    DegradedDetected,
58    /// A restriction policy was activated.
59    RestrictedDetected,
60    /// Graceful shutdown was requested.
61    ShutdownRequested,
62    /// Graceful shutdown completed.
63    ShutdownCompleted,
64    /// A degraded or restricted condition recovered.
65    RecoveryCompleted,
66}
67
68/// Thread-safe state machine for the Runtime process lifecycle.
69#[derive(Debug)]
70pub struct RuntimeLifecycle {
71    machine: Mutex<StateMachine>,
72}
73
74impl Clone for RuntimeLifecycle {
75    fn clone(&self) -> Self {
76        let guard = self.machine.lock();
77        Self {
78            machine: Mutex::new(guard.clone()),
79        }
80    }
81}
82
83impl RuntimeLifecycleState {
84    fn as_state_name(self) -> StateName {
85        StateName::new(match self {
86            RuntimeLifecycleState::Booting => "Booting",
87            RuntimeLifecycleState::LoadingConfig => "LoadingConfig",
88            RuntimeLifecycleState::CheckingSecurity => "CheckingSecurity",
89            RuntimeLifecycleState::OpeningStorage => "OpeningStorage",
90            RuntimeLifecycleState::StartingApi => "StartingApi",
91            RuntimeLifecycleState::Running => "Running",
92            RuntimeLifecycleState::Degraded => "Degraded",
93            RuntimeLifecycleState::Restricted => "Restricted",
94            RuntimeLifecycleState::ShuttingDown => "ShuttingDown",
95            RuntimeLifecycleState::Stopped => "Stopped",
96        })
97        .unwrap()
98    }
99
100    fn from_state_name(state: &StateName) -> RuntimeResult<Self> {
101        match state.as_str() {
102            "Booting" => Ok(Self::Booting),
103            "LoadingConfig" => Ok(Self::LoadingConfig),
104            "CheckingSecurity" => Ok(Self::CheckingSecurity),
105            "OpeningStorage" => Ok(Self::OpeningStorage),
106            "StartingApi" => Ok(Self::StartingApi),
107            "Running" => Ok(Self::Running),
108            "Degraded" => Ok(Self::Degraded),
109            "Restricted" => Ok(Self::Restricted),
110            "ShuttingDown" => Ok(Self::ShuttingDown),
111            "Stopped" => Ok(Self::Stopped),
112            _ => Err(RuntimeError::InvalidStateTransition),
113        }
114    }
115}
116
117impl RuntimeLifecycleEvent {
118    fn as_event_name(self) -> EventName {
119        EventName::new(match self {
120            RuntimeLifecycleEvent::ConfigLoaded => "ConfigLoaded",
121            RuntimeLifecycleEvent::SecurityChecked => "SecurityChecked",
122            RuntimeLifecycleEvent::StorageOpened => "StorageOpened",
123            RuntimeLifecycleEvent::ApiStarted => "ApiStarted",
124            RuntimeLifecycleEvent::DegradedDetected => "DegradedDetected",
125            RuntimeLifecycleEvent::RestrictedDetected => "RestrictedDetected",
126            RuntimeLifecycleEvent::ShutdownRequested => "ShutdownRequested",
127            RuntimeLifecycleEvent::ShutdownCompleted => "ShutdownCompleted",
128            RuntimeLifecycleEvent::RecoveryCompleted => "RecoveryCompleted",
129        })
130        .unwrap()
131    }
132}
133
134impl RuntimeLifecycle {
135    /// Creates a lifecycle in the booting state with all valid transitions.
136    pub fn new() -> Self {
137        // Máquina de estados explícita para o ciclo de vida do runtime.
138        // Todas as transições são rígidas e validadas; qualquer transição inválida gera erro imediato
139        // e impede o avanço de estado incorreto.
140        let mut machine = StateMachine::new(RuntimeLifecycleState::Booting.as_state_name());
141        let transitions = vec![
142            (
143                RuntimeLifecycleState::Booting,
144                RuntimeLifecycleEvent::ConfigLoaded,
145                RuntimeLifecycleState::CheckingSecurity,
146            ),
147            (
148                RuntimeLifecycleState::CheckingSecurity,
149                RuntimeLifecycleEvent::SecurityChecked,
150                RuntimeLifecycleState::OpeningStorage,
151            ),
152            (
153                RuntimeLifecycleState::OpeningStorage,
154                RuntimeLifecycleEvent::StorageOpened,
155                RuntimeLifecycleState::StartingApi,
156            ),
157            (
158                RuntimeLifecycleState::StartingApi,
159                RuntimeLifecycleEvent::ApiStarted,
160                RuntimeLifecycleState::Running,
161            ),
162            (
163                RuntimeLifecycleState::Running,
164                RuntimeLifecycleEvent::DegradedDetected,
165                RuntimeLifecycleState::Degraded,
166            ),
167            (
168                RuntimeLifecycleState::Running,
169                RuntimeLifecycleEvent::RestrictedDetected,
170                RuntimeLifecycleState::Restricted,
171            ),
172            (
173                RuntimeLifecycleState::Degraded,
174                RuntimeLifecycleEvent::RecoveryCompleted,
175                RuntimeLifecycleState::Running,
176            ),
177            (
178                RuntimeLifecycleState::Restricted,
179                RuntimeLifecycleEvent::RecoveryCompleted,
180                RuntimeLifecycleState::Running,
181            ),
182            (
183                RuntimeLifecycleState::Running,
184                RuntimeLifecycleEvent::ShutdownRequested,
185                RuntimeLifecycleState::ShuttingDown,
186            ),
187            (
188                RuntimeLifecycleState::Degraded,
189                RuntimeLifecycleEvent::ShutdownRequested,
190                RuntimeLifecycleState::ShuttingDown,
191            ),
192            (
193                RuntimeLifecycleState::Restricted,
194                RuntimeLifecycleEvent::ShutdownRequested,
195                RuntimeLifecycleState::ShuttingDown,
196            ),
197            (
198                RuntimeLifecycleState::ShuttingDown,
199                RuntimeLifecycleEvent::ShutdownCompleted,
200                RuntimeLifecycleState::Stopped,
201            ),
202        ];
203
204        for (from, event, to) in transitions {
205            let _ = machine.add_transition(StateTransition {
206                from: from.as_state_name(),
207                event: event.as_event_name(),
208                to: to.as_state_name(),
209            });
210        }
211
212        Self {
213            machine: Mutex::new(machine),
214        }
215    }
216
217    /// Returns the current lifecycle state.
218    pub fn current(&self) -> RuntimeLifecycleState {
219        let guard = self.machine.lock();
220        match RuntimeLifecycleState::from_state_name(guard.current()) {
221            Ok(state) => state,
222            Err(_) => RuntimeLifecycleState::Booting,
223        }
224    }
225
226    /// Applies one lifecycle event and returns the resulting state.
227    pub fn apply(&self, event: RuntimeLifecycleEvent) -> RuntimeResult<RuntimeLifecycleState> {
228        let mut guard = self.machine.lock();
229        let next = guard.apply(&event.as_event_name())?;
230        RuntimeLifecycleState::from_state_name(next)
231    }
232
233    /// Reports whether the lifecycle is in the normal running state.
234    pub fn is_running(&self) -> bool {
235        self.current() == RuntimeLifecycleState::Running
236    }
237
238    /// Reports whether shutdown has completed.
239    pub fn is_stopped(&self) -> bool {
240        self.current() == RuntimeLifecycleState::Stopped
241    }
242
243    /// Reports whether restricted operation is active.
244    pub fn is_restricted(&self) -> bool {
245        self.current() == RuntimeLifecycleState::Restricted
246    }
247}
248
249impl Default for RuntimeLifecycle {
250    fn default() -> Self {
251        Self::new()
252    }
253}
254
255#[cfg(test)]
256#[path = "lifecycle_tests.rs"]
257mod tests;