Skip to main content

oxihuman_core/
health_monitor.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5pub struct HealthMonitor {
6    pub checks: Vec<(String, bool)>,
7}
8
9impl HealthMonitor {
10    pub fn new() -> Self {
11        HealthMonitor { checks: Vec::new() }
12    }
13}
14
15impl Default for HealthMonitor {
16    fn default() -> Self {
17        Self::new()
18    }
19}
20
21pub fn new_health_monitor() -> HealthMonitor {
22    HealthMonitor::new()
23}
24
25pub fn health_register(m: &mut HealthMonitor, name: &str, healthy: bool) {
26    m.checks.push((name.to_string(), healthy));
27}
28
29/// Update an existing check. Returns true if the check was found.
30pub fn health_update(m: &mut HealthMonitor, name: &str, healthy: bool) -> bool {
31    for (n, h) in &mut m.checks {
32        if n == name {
33            *h = healthy;
34            return true;
35        }
36    }
37    false
38}
39
40pub fn health_all_ok(m: &HealthMonitor) -> bool {
41    m.checks.iter().all(|(_, h)| *h)
42}
43
44pub fn health_count(m: &HealthMonitor) -> usize {
45    m.checks.len()
46}
47
48pub fn health_failing_count(m: &HealthMonitor) -> usize {
49    m.checks.iter().filter(|(_, h)| !h).count()
50}
51
52pub fn health_summary(m: &HealthMonitor) -> String {
53    let total = m.checks.len();
54    let failing = health_failing_count(m);
55    format!("checks={} failing={}", total, failing)
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn test_new_empty() {
64        /* new monitor has no checks */
65        let m = new_health_monitor();
66        assert_eq!(health_count(&m), 0);
67    }
68
69    #[test]
70    fn test_register_healthy() {
71        /* register adds a healthy check */
72        let mut m = new_health_monitor();
73        health_register(&mut m, "db", true);
74        assert!(health_all_ok(&m));
75    }
76
77    #[test]
78    fn test_register_failing() {
79        /* register adds a failing check */
80        let mut m = new_health_monitor();
81        health_register(&mut m, "db", false);
82        assert!(!health_all_ok(&m));
83        assert_eq!(health_failing_count(&m), 1);
84    }
85
86    #[test]
87    fn test_update_existing() {
88        /* update changes check status */
89        let mut m = new_health_monitor();
90        health_register(&mut m, "svc", false);
91        assert!(health_update(&mut m, "svc", true));
92        assert!(health_all_ok(&m));
93    }
94
95    #[test]
96    fn test_update_missing() {
97        /* update returns false for unknown check */
98        let mut m = new_health_monitor();
99        assert!(!health_update(&mut m, "ghost", true));
100    }
101
102    #[test]
103    fn test_failing_count() {
104        /* failing count is correct */
105        let mut m = new_health_monitor();
106        health_register(&mut m, "a", true);
107        health_register(&mut m, "b", false);
108        health_register(&mut m, "c", false);
109        assert_eq!(health_failing_count(&m), 2);
110    }
111
112    #[test]
113    fn test_summary_format() {
114        /* summary contains expected fields */
115        let mut m = new_health_monitor();
116        health_register(&mut m, "x", true);
117        health_register(&mut m, "y", false);
118        let s = health_summary(&m);
119        assert!(s.contains("checks=2"));
120        assert!(s.contains("failing=1"));
121    }
122}