Skip to main content

lightshuttle_runtime/lifecycle/
status.rs

1//! Per-node status and lifecycle event types.
2//!
3//! [`NodeStatus`] is the fine-grained internal status carried by each
4//! `tokio::sync::watch` channel inside the manager. [`LifecycleEvent`] is the
5//! externally broadcast event emitted on the `tokio::sync::broadcast` channel
6//! returned by [`crate::LifecycleManager::subscribe_events`].
7//!
8//! The two types serve different consumers: `NodeStatus` is used internally by
9//! `start_one` to gate dependency ordering; `LifecycleEvent` is consumed by
10//! CLI progress bars, dashboard WebSocket connections, and test assertions.
11
12use serde::Serialize;
13
14/// Lifecycle status of a single managed resource.
15///
16/// Broadcast through a `tokio::sync::watch` channel so dependents can
17/// wait for their dependencies to become ready without polling.
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum NodeStatus {
20    /// The resource has not been started yet.
21    Pending,
22    /// The runtime accepted the start request; the container is booting.
23    Starting,
24    /// The container is up but does not declare a healthcheck or has
25    /// not produced a healthcheck result yet.
26    Running,
27    /// The container is up and reports a successful healthcheck.
28    Healthy,
29    /// The resource entered a terminal failure state with the recorded
30    /// reason.
31    Failed {
32        /// Free-form failure reason for diagnostics.
33        reason: String,
34    },
35    /// The resource has been stopped on request.
36    Stopped,
37}
38
39impl NodeStatus {
40    /// Whether the resource is considered ready for dependents to
41    /// start on top of it.
42    #[must_use]
43    pub fn is_ready(&self) -> bool {
44        matches!(self, Self::Healthy | Self::Running)
45    }
46
47    /// Whether the resource is in a terminal state (failed or stopped).
48    #[must_use]
49    pub fn is_terminal(&self) -> bool {
50        matches!(self, Self::Failed { .. } | Self::Stopped)
51    }
52}
53
54/// Event emitted by [`crate::LifecycleManager`] for consumption by a
55/// CLI, dashboard or test harness.
56#[derive(Debug, Clone, Serialize)]
57#[serde(tag = "type", rename_all = "snake_case")]
58pub enum LifecycleEvent {
59    /// A resource has been created and started by the runtime.
60    ResourceStarted {
61        /// Resource name as declared in the manifest.
62        name: String,
63        /// Container identifier returned by the runtime.
64        container_id: String,
65    },
66    /// A resource passed its healthcheck.
67    ResourceHealthy {
68        /// Resource name.
69        name: String,
70    },
71    /// A resource failed and will not run.
72    ResourceFailed {
73        /// Resource name.
74        name: String,
75        /// Human-readable failure description.
76        error: String,
77    },
78    /// A resource has been stopped cleanly.
79    ResourceStopped {
80        /// Resource name.
81        name: String,
82    },
83    /// Every resource has reached a ready state.
84    StackStarted,
85    /// The manager has started rolling the stack down.
86    StackStopping,
87    /// Every resource has been stopped.
88    StackStopped,
89}