use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HealthStatus {
Healthy,
Unhealthy,
}
#[derive(Debug, Clone)]
pub struct HealthChecker {
ready: Arc<AtomicBool>,
alive: Arc<AtomicBool>,
}
impl HealthChecker {
pub fn new() -> Self {
Self {
ready: Arc::new(AtomicBool::new(false)),
alive: Arc::new(AtomicBool::new(true)),
}
}
pub fn set_ready(&self, ready: bool) {
self.ready.store(ready, Ordering::SeqCst);
}
pub fn set_alive(&self, alive: bool) {
self.alive.store(alive, Ordering::SeqCst);
}
pub fn is_ready(&self) -> bool {
self.ready.load(Ordering::SeqCst)
}
pub fn is_alive(&self) -> bool {
self.alive.load(Ordering::SeqCst)
}
pub fn status(&self) -> HealthStatus {
if self.is_alive() && self.is_ready() {
HealthStatus::Healthy
} else {
HealthStatus::Unhealthy
}
}
}
impl Default for HealthChecker {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_health_checker_creation() {
let checker = HealthChecker::new();
assert!(!checker.is_ready()); assert!(checker.is_alive()); assert_eq!(checker.status(), HealthStatus::Unhealthy);
}
#[test]
fn test_set_ready() {
let checker = HealthChecker::new();
checker.set_ready(true);
assert!(checker.is_ready());
assert_eq!(checker.status(), HealthStatus::Healthy);
}
#[test]
fn test_set_alive() {
let checker = HealthChecker::new();
checker.set_ready(true);
checker.set_alive(false);
assert!(!checker.is_alive());
assert_eq!(checker.status(), HealthStatus::Unhealthy);
}
#[test]
fn test_health_status() {
let checker = HealthChecker::new();
assert_eq!(checker.status(), HealthStatus::Unhealthy);
checker.set_ready(true);
assert_eq!(checker.status(), HealthStatus::Healthy);
checker.set_alive(false);
assert_eq!(checker.status(), HealthStatus::Unhealthy);
}
}