rust_supervisor/state/supervisor.rs
1//! Supervisor current-state model.
2//!
3//! The module owns the current tree state returned to callers. It stores child
4//! state by stable path and avoids retaining event history.
5
6use crate::event::time::EventSequence;
7use crate::id::types::SupervisorPath;
8use crate::state::child::ChildState;
9use serde::{Deserialize, Serialize};
10use std::collections::BTreeMap;
11
12/// Shutdown state visible in current state.
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub enum ShutdownState {
15 /// Shutdown has not started.
16 Idle,
17 /// Stop was requested.
18 RequestStop,
19 /// Runtime waits for graceful task completion.
20 GracefulDrain,
21 /// Runtime aborts straggling async workers.
22 AbortStragglers,
23 /// Runtime reconciles registry, state, metrics, and journal.
24 Reconcile,
25 /// Shutdown completed.
26 Completed,
27}
28
29/// Meltdown status visible in current state.
30#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
31pub enum MeltdownState {
32 /// No fuse is tripped.
33 Clear,
34 /// A child-level fuse is tripped.
35 ChildFuseTripped {
36 /// Path that tripped the fuse.
37 path: SupervisorPath,
38 },
39 /// A supervisor-level fuse is tripped.
40 SupervisorFuseTripped {
41 /// Path that tripped the fuse.
42 path: SupervisorPath,
43 },
44}
45
46/// Current state for a supervisor tree.
47#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
48pub struct SupervisorState {
49 /// Root path for this state response.
50 pub root_path: SupervisorPath,
51 /// Generated time in nanoseconds since the Unix epoch.
52 pub generated_at_unix_nanos: u128,
53 /// Sequence assigned to this state generation.
54 pub sequence: EventSequence,
55 /// Configuration version that produced this state.
56 pub config_version: u64,
57 /// Child states indexed by stable path text.
58 pub children: BTreeMap<String, ChildState>,
59 /// Current meltdown status.
60 pub meltdown_state: MeltdownState,
61 /// Current shutdown status.
62 pub shutdown_state: ShutdownState,
63 /// Last event journal sequence known to the state owner.
64 pub journal_sequence: Option<EventSequence>,
65}
66
67impl SupervisorState {
68 /// Creates an empty supervisor current state.
69 ///
70 /// # Arguments
71 ///
72 /// - `root_path`: Root path for the state response.
73 /// - `sequence`: State generation sequence.
74 /// - `config_version`: Configuration version that produced the state.
75 ///
76 /// # Returns
77 ///
78 /// Returns a [`SupervisorState`] without children.
79 ///
80 /// # Examples
81 ///
82 /// ```
83 /// let state = rust_supervisor::state::supervisor::SupervisorState::new(
84 /// rust_supervisor::id::types::SupervisorPath::root(),
85 /// rust_supervisor::event::time::EventSequence::new(1),
86 /// 1,
87 /// );
88 /// assert!(state.children.is_empty());
89 /// ```
90 pub fn new(root_path: SupervisorPath, sequence: EventSequence, config_version: u64) -> Self {
91 Self {
92 root_path,
93 generated_at_unix_nanos: crate::state::supervisor::unix_nanos_now(),
94 sequence,
95 config_version,
96 children: BTreeMap::new(),
97 meltdown_state: MeltdownState::Clear,
98 shutdown_state: ShutdownState::Idle,
99 journal_sequence: None,
100 }
101 }
102
103 /// Inserts or replaces one child state.
104 ///
105 /// # Arguments
106 ///
107 /// - `child`: Current state for one child.
108 ///
109 /// # Returns
110 ///
111 /// Returns the updated [`SupervisorState`].
112 pub fn with_child(mut self, child: ChildState) -> Self {
113 self.children.insert(child.path.to_string(), child);
114 self
115 }
116
117 /// Updates shutdown state.
118 ///
119 /// # Arguments
120 ///
121 /// - `shutdown_state`: New shutdown phase.
122 ///
123 /// # Returns
124 ///
125 /// Returns the updated [`SupervisorState`].
126 pub fn with_shutdown_state(mut self, shutdown_state: ShutdownState) -> Self {
127 self.shutdown_state = shutdown_state;
128 self
129 }
130
131 /// Updates meltdown state.
132 ///
133 /// # Arguments
134 ///
135 /// - `meltdown_state`: New meltdown state.
136 ///
137 /// # Returns
138 ///
139 /// Returns the updated [`SupervisorState`].
140 pub fn with_meltdown_state(mut self, meltdown_state: MeltdownState) -> Self {
141 self.meltdown_state = meltdown_state;
142 self
143 }
144
145 /// Records the latest journal sequence known to this state.
146 ///
147 /// # Arguments
148 ///
149 /// - `journal_sequence`: Latest event sequence from the journal.
150 ///
151 /// # Returns
152 ///
153 /// Returns the updated [`SupervisorState`].
154 pub fn with_journal_sequence(mut self, journal_sequence: EventSequence) -> Self {
155 self.journal_sequence = Some(journal_sequence);
156 self
157 }
158}
159
160/// Reads the current wall-clock time as nanoseconds since Unix epoch.
161///
162/// # Arguments
163///
164/// This function has no arguments.
165///
166/// # Returns
167///
168/// Returns zero when the system clock is before the Unix epoch.
169fn unix_nanos_now() -> u128 {
170 std::time::SystemTime::now()
171 .duration_since(std::time::UNIX_EPOCH)
172 .unwrap_or(std::time::Duration::ZERO)
173 .as_nanos()
174}