Skip to main content

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}