appcore_supervisor/health.rs
1// =============================================================================
2// #######
3// ### ### F: health.rs
4// ## ## ## ## P: AppCore-Runtime
5// ## ##
6// C: 2026/07/24 11:51:10 by dnettoRaw
7// ## ## ## ## U: 2026/07/24 13:18:47 by dnettoRaw
8// ########### S: 1.0.1-rc.8
9// =============================================================================
10
11//! Stable health, activation, dependency, and runtime states.
12
13/// Observable health of one managed service.
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum ServiceHealth {
16 /// Startup completed and the service can accept work.
17 Ready,
18 /// The service is running within its declared health policy.
19 Healthy,
20 /// The service remains available with reduced guarantees.
21 Degraded,
22 /// The service cannot provide its responsibility.
23 Failed,
24 /// Service startup is in progress.
25 Starting,
26 /// Cooperative shutdown is in progress.
27 Stopping,
28 /// The service has not produced a trustworthy health signal.
29 Unknown,
30}
31
32impl ServiceHealth {
33 /// Reports whether a compatibility dependency may use this service.
34 pub fn dependency_ready(self) -> bool {
35 matches!(self, Self::Ready | Self::Healthy | Self::Degraded)
36 }
37
38 /// Reports whether the service is in a failed state.
39 pub fn is_failed(self) -> bool {
40 self == Self::Failed
41 }
42}
43
44/// Installation-level activation of one managed service.
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub enum ServiceActivationState {
47 /// The service is configured and participates in lifecycle management.
48 Enabled,
49 /// The service is intentionally disabled by deployment policy.
50 Disabled,
51 /// The deployment has no provider or configuration for the service.
52 NotConfigured,
53}
54
55impl ServiceActivationState {
56 /// Reports whether lifecycle actions may run for this service.
57 pub fn is_enabled(self) -> bool {
58 self == Self::Enabled
59 }
60
61 /// Reports whether deployment configuration exists for this service.
62 pub fn is_configured(self) -> bool {
63 self != Self::NotConfigured
64 }
65}
66
67/// Concrete execution state of one managed service.
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub enum ServiceRuntimeState {
70 /// Startup is in progress.
71 Starting,
72 /// The service currently owns its declared resource.
73 Running,
74 /// Cooperative stop was requested.
75 StopRequested,
76 /// Shutdown is in progress.
77 Stopping,
78 /// No service instance owns the resource.
79 Stopped,
80 /// A restart has been scheduled.
81 RestartScheduled,
82 /// A restart worker is executing lifecycle actions.
83 Restarting,
84 /// A previous instance outlived its shutdown timeout.
85 Orphaned,
86 /// Automatic lifecycle actions are disabled pending operator action.
87 Quarantined,
88 /// The service failed without a live orphan.
89 Failed,
90}
91
92impl ServiceRuntimeState {
93 /// Reports whether the service may still own an external resource.
94 pub fn owns_resource(self) -> bool {
95 matches!(
96 self,
97 Self::Starting
98 | Self::Running
99 | Self::StopRequested
100 | Self::Stopping
101 | Self::Restarting
102 | Self::Orphaned
103 )
104 }
105}
106
107/// Minimum health accepted from a declared dependency.
108#[derive(Debug, Clone, Copy, PartialEq, Eq)]
109pub enum DependencyRequirement {
110 /// Accept a dependency that is ready or healthy.
111 Ready,
112 /// Require a steady healthy dependency.
113 Healthy,
114 /// Permit ready, healthy, or explicitly degraded operation.
115 DegradedAllowed,
116 /// Never block the dependent when this dependency is absent or unhealthy.
117 Optional,
118}
119
120impl DependencyRequirement {
121 /// Reports whether `health` satisfies this requirement.
122 pub fn accepts(self, health: ServiceHealth) -> bool {
123 match self {
124 Self::Ready => matches!(health, ServiceHealth::Ready | ServiceHealth::Healthy),
125 Self::Healthy => health == ServiceHealth::Healthy,
126 Self::DegradedAllowed => health.dependency_ready(),
127 Self::Optional => true,
128 }
129 }
130}