use serde::Deserialize;
#[derive(Deserialize)]
pub struct Envelope {
pub success: bool,
pub data: serde_json::Value,
pub error: Option<String>,
pub meta: Option<Meta>,
}
#[derive(Deserialize)]
pub struct Meta {
pub duration_ms: Option<f64>,
pub daemon_rss_kb: Option<u64>,
pub daemon_uptime_secs: Option<u64>,
pub daemon_connections: Option<u32>,
}
pub fn daemon_alive(port: u16) -> bool {
let url = format!("http://127.0.0.1:{}/api/health", port);
reqwest::blocking::get(&url).is_ok()
}
pub fn health(port: u16, json_output: bool) -> Result<(), Box<dyn std::error::Error>> {
let url = format!("http://127.0.0.1:{}/api/health", port);
match reqwest::blocking::get(&url) {
Ok(resp) => {
if let Ok(e) = resp.json::<Envelope>() {
if e.success {
let d = &e.data;
let pid = d.get("pid").and_then(|v| v.as_u64()).unwrap_or(0);
let rss = d.get("rss_kb").and_then(|v| v.as_u64()).unwrap_or(0);
let uptime = d.get("uptime_secs").and_then(|v| v.as_u64()).unwrap_or(0);
let conns = d.get("connections").and_then(|v| v.as_u64()).unwrap_or(0);
let ver = d.get("version").and_then(|v| v.as_str()).unwrap_or("?");
if json_output {
println!("{}", serde_json::to_string_pretty(&e.data)?);
} else {
let rss_mb = rss as f64 / 1024.0;
let (uptime_str, _) = format_duration(uptime);
println!(" ● nomad-daemon: RUNNING");
println!(" PID: {pid}");
println!(" Port: {port}");
println!(" RSS: {rss_mb:.1} MB");
println!(" Uptime: {uptime_str}");
println!(" Conns: {conns}");
println!(" Ver: {ver}");
}
} else {
let err = e.error.unwrap_or_else(|| "unknown".into());
if json_output {
println!(r#"{{"running":false,"error":"{err}"}}"#);
} else {
println!(" ● nomad-daemon: ERROR {err}");
}
}
}
}
Err(_) => {
if json_output {
println!(r#"{{"running":false}}"#);
} else {
println!(" ● nomad-daemon: STOPPED. Start with: nom daemon start");
}
}
}
Ok(())
}
fn format_duration(secs: u64) -> (String, u64) {
let h = secs / 3600;
let m = (secs % 3600) / 60;
let s = secs % 60;
if h > 0 {
(format!("{h}h {m}m"), secs)
} else if m > 0 {
(format!("{m}m {s}s"), secs)
} else {
(format!("{s}s"), secs)
}
}