procref 0.1.0

Cross-platform process reference counting for shared service lifecycle management
Documentation
//! Common types for procref.

use std::collections::HashMap;

/// Information about a running service.
///
/// This is the data returned by `on_first_acquire` and passed to other callbacks.
/// Users can store any service-specific information here.
#[derive(Debug, Clone)]
pub struct ServiceInfo {
    /// Process ID of the service.
    pid: u32,

    /// Port the service is listening on (if applicable).
    port: u16,

    /// Additional metadata (user-defined).
    metadata: HashMap<String, String>,
}

impl ServiceInfo {
    /// Create a new ServiceInfo with PID and port.
    pub fn new(pid: u32, port: u16) -> Self {
        Self {
            pid,
            port,
            metadata: HashMap::new(),
        }
    }

    /// Create a ServiceInfo with only PID (no port).
    pub fn with_pid(pid: u32) -> Self {
        Self {
            pid,
            port: 0,
            metadata: HashMap::new(),
        }
    }

    /// Get the process ID.
    pub fn pid(&self) -> u32 {
        self.pid
    }

    /// Get the port number.
    pub fn port(&self) -> u16 {
        self.port
    }

    /// Set a metadata value.
    pub fn set_metadata(&mut self, key: impl Into<String>, value: impl Into<String>) {
        self.metadata.insert(key.into(), value.into());
    }

    /// Get a metadata value.
    pub fn get_metadata(&self, key: &str) -> Option<&str> {
        self.metadata.get(key).map(|s| s.as_str())
    }

    /// Check if the service process is still alive.
    pub fn is_alive(&self) -> bool {
        crate::process::is_alive(self.pid)
    }
}

/// Serializable version of ServiceInfo for file storage.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub(crate) struct ServiceInfoFile {
    pub pid: u32,
    pub port: u16,
    #[serde(default)]
    pub metadata: HashMap<String, String>,
    #[serde(default)]
    pub started_at: Option<String>,
}

impl From<&ServiceInfo> for ServiceInfoFile {
    fn from(info: &ServiceInfo) -> Self {
        Self {
            pid: info.pid,
            port: info.port,
            metadata: info.metadata.clone(),
            started_at: Some(chrono::Utc::now().to_rfc3339()),
        }
    }
}

impl From<ServiceInfoFile> for ServiceInfo {
    fn from(file: ServiceInfoFile) -> Self {
        Self {
            pid: file.pid,
            port: file.port,
            metadata: file.metadata,
        }
    }
}