hot-restart 0.6.16

A Rust library for hot restarting applications without downtime. Provides seamless process replacement for servers and long-running services, enabling zero-downtime updates and configuration reloads.
Documentation
use crate::*;

/// Internal function to handle hot restart process.
///
/// # Arguments
///
/// - `&[&str]` - Arguments to pass to cargo-watch.
/// - `bool` - Whether to wait for process completion.
/// - `F` - The future to run before hot restart.
///
/// # Returns
///
/// - `ResultHotRestartError` - Result of hot restart operation.
async fn run_hot_restart<F>(run_args: &[&str], wait: bool, before_hook: F) -> ResultHotRestartError
where
    F: Future<Output = ()>,
{
    before_hook.await;
    let check_output: Output = Command::new("cargo")
        .args(["install", "--list"])
        .output()
        .map_err(|e| HotRestartError::Other(e.to_string()))?;
    let check_output_str: Cow<'_, str> = String::from_utf8_lossy(&check_output.stdout);
    if !check_output_str.contains("cargo-watch") {
        eprintln!("Cargo-watch is not installed. Attempting to install...");
        let install_status: ExitStatus = Command::new("cargo")
            .args(["install", "cargo-watch"])
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()?
            .wait()?;
        if !install_status.success() {
            return Err(HotRestartError::CargoWatchNotInstalled);
        }
        eprintln!("Cargo-watch installed successfully.");
    }
    let mut command: Command = Command::new("cargo-watch");
    command
        .args(run_args)
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .stdin(Stdio::inherit());
    let mut child: Child = command
        .spawn()
        .map_err(|e| HotRestartError::CommandSpawnFailed(e.to_string()))?;
    if wait {
        child
            .wait()
            .map_err(|e| HotRestartError::CommandWaitFailed(e.to_string()))?;
    }
    exit(0);
}

/// Starts hot restart process without waiting for completion.
///
/// # Arguments
///
/// - `&[&str]` - Arguments to pass to cargo-watch.
/// - `F` - The future to run before hot restart.
///
/// # Returns
///
/// - `ResultHotRestartError` - Result of hot restart operation.
pub async fn hot_restart<F>(run_args: &[&str], before_hook: F) -> ResultHotRestartError
where
    F: Future<Output = ()>,
{
    run_hot_restart(run_args, false, before_hook).await
}

/// Starts hot restart process and waits for completion.
///
/// # Arguments
///
/// - `&[&str]` - Arguments to pass to cargo-watch.
/// - `F` - The future to run before hot restart.
///
/// # Returns
///
/// - `ResultHotRestartError` - Result of hot restart operation.
pub async fn hot_restart_wait<F>(run_args: &[&str], before_hook: F) -> ResultHotRestartError
where
    F: Future<Output = ()>,
{
    run_hot_restart(run_args, true, before_hook).await
}