mecha10_runtime/
health.rs1use std::collections::HashMap;
4use std::sync::Arc;
5use std::time::Duration;
6use tokio::sync::RwLock;
7
8#[derive(Clone, Debug, PartialEq)]
10pub enum HealthStatus {
11 Healthy,
13
14 Degraded { reason: String },
16
17 Unhealthy { reason: String },
19}
20
21impl HealthStatus {
22 pub fn is_healthy(&self) -> bool {
24 matches!(self, HealthStatus::Healthy)
25 }
26
27 pub fn is_degraded(&self) -> bool {
29 matches!(self, HealthStatus::Degraded { .. })
30 }
31
32 pub fn is_unhealthy(&self) -> bool {
34 matches!(self, HealthStatus::Unhealthy { .. })
35 }
36
37 pub fn reason(&self) -> Option<&str> {
39 match self {
40 HealthStatus::Healthy => None,
41 HealthStatus::Degraded { reason } => Some(reason),
42 HealthStatus::Unhealthy { reason } => Some(reason),
43 }
44 }
45}
46
47pub struct HealthChecker {
49 checks: Arc<RwLock<HashMap<String, HealthStatus>>>,
50 interval: Duration,
51}
52
53impl HealthChecker {
54 pub fn new(interval: Duration) -> Self {
56 Self {
57 checks: Arc::new(RwLock::new(HashMap::new())),
58 interval,
59 }
60 }
61
62 pub async fn register(&self, name: String, initial_status: HealthStatus) {
64 let mut checks = self.checks.write().await;
65 checks.insert(name, initial_status);
66 }
67
68 pub async fn update(&self, name: &str, status: HealthStatus) {
70 let mut checks = self.checks.write().await;
71 checks.insert(name.to_string(), status);
72 }
73
74 pub async fn check_one(&self, name: &str) -> Option<HealthStatus> {
76 let checks = self.checks.read().await;
77 checks.get(name).cloned()
78 }
79
80 pub async fn check_all(&self) -> HashMap<String, HealthStatus> {
82 let checks = self.checks.read().await;
83 checks.clone()
84 }
85
86 pub fn interval(&self) -> Duration {
88 self.interval
89 }
90
91 pub async fn unregister(&self, name: &str) {
93 let mut checks = self.checks.write().await;
94 checks.remove(name);
95 }
96}