Skip to main content

agent_procs/
session.rs

1//! Daemon health checks and unique ID generation.
2//!
3//! [`is_daemon_alive`] probes a PID file to determine whether a session's
4//! daemon process is still running.  [`IdCounter`] hands out sequential
5//! process identifiers (`p1`, `p2`, …) within a daemon's lifetime.
6
7use std::fs;
8use std::path::Path;
9
10#[must_use]
11pub fn is_daemon_alive(pid_path: &Path) -> bool {
12    let content = match fs::read_to_string(pid_path) {
13        Ok(c) => c,
14        Err(_) => return false,
15    };
16    let pid: i32 = match content.trim().parse() {
17        Ok(p) => p,
18        Err(_) => return false,
19    };
20    nix::sys::signal::kill(nix::unistd::Pid::from_raw(pid), None).is_ok()
21}
22
23pub struct IdCounter {
24    next_id: u32,
25}
26
27impl Default for IdCounter {
28    fn default() -> Self {
29        Self::new()
30    }
31}
32
33impl IdCounter {
34    pub fn new() -> Self {
35        Self { next_id: 1 }
36    }
37    pub fn next_id(&mut self) -> String {
38        let id = format!("p{}", self.next_id);
39        self.next_id += 1;
40        id
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn test_id_counter_sequential() {
50        let mut counter = IdCounter::new();
51        assert_eq!(counter.next_id(), "p1");
52        assert_eq!(counter.next_id(), "p2");
53        assert_eq!(counter.next_id(), "p3");
54    }
55
56    #[test]
57    fn test_id_counter_default() {
58        let mut counter = IdCounter::default();
59        assert_eq!(counter.next_id(), "p1");
60    }
61}