use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SubsystemHealth {
Starting,
Running,
Draining,
Stopped,
Failed { reason: String },
}
impl SubsystemHealth {
pub fn is_healthy(&self) -> bool {
matches!(self, SubsystemHealth::Starting | SubsystemHealth::Running)
}
}
#[derive(Clone, Default)]
pub struct ClusterHealth {
inner: Arc<RwLock<HashMap<&'static str, SubsystemHealth>>>,
}
impl ClusterHealth {
pub fn new() -> Self {
Self::default()
}
pub async fn set(&self, name: &'static str, health: SubsystemHealth) {
let mut map = self.inner.write().await;
map.insert(name, health);
}
pub async fn get(&self, name: &'static str) -> Option<SubsystemHealth> {
let map = self.inner.read().await;
map.get(name).cloned()
}
pub async fn all_running(&self) -> bool {
let map = self.inner.read().await;
map.values().all(|h| *h == SubsystemHealth::Running)
}
pub async fn failed_subsystems(&self) -> Vec<&'static str> {
let map = self.inner.read().await;
map.iter()
.filter_map(|(name, h)| {
if matches!(h, SubsystemHealth::Failed { .. }) {
Some(*name)
} else {
None
}
})
.collect()
}
pub async fn snapshot(&self) -> HashMap<&'static str, SubsystemHealth> {
self.inner.read().await.clone()
}
}