# systemd_reload: Zero-downtime Process Management for Rust Applications

A high-performance Rust library that provides systemd-style process management with zero-downtime rolling updates, graceful shutdown, and automatic failure recovery.

## Table of Contents

- [Features](#features)
- [Quick Start](#quick-start)
- [API Reference](#api-reference)
- [Architecture](#architecture)
- [Technology Stack](#technology-stack)
- [Project Structure](#project-structure)
- [Examples](#examples)
- [Historical Context](#historical-context)

## Features

- **Zero-downtime Rolling Updates**: Seamlessly replace running processes without service interruption
- **Graceful Shutdown**: Proper signal handling for clean process termination
- **Automatic Recovery**: Restart failed processes automatically
- **High Performance**: Built with crossfire async message queues for minimal overhead
- **Signal Management**: Handle SIGHUP for reload, SIGTERM/SIGINT for shutdown
- **Worker Mode Detection**: Prevent infinite recursion during process spawning

## Quick Start

Add to your `Cargo.toml`:

```toml
[dependencies]
systemd_reload = "0.1.0"
```

Basic usage:

```rust
use systemd_reload::{run, is_worker};

#[tokio::main]
async fn main() {
    if is_worker() {
        // Worker process: run your main application logic
        run_application().await;
    } else {
        // Supervisor process: manage workers
        run().await;
    }
}

async fn run_application() {
    // Your actual application code goes here
    println!("Worker process started, PID: {}", std::process::id());
    
    // Example: web server, background task, etc.
    loop {
        // Your business logic
        tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
    }
}
```

## API Reference

### Core Types

#### `Run`
The main process manager that handles worker lifecycle.

```rust
impl Run {
    pub fn new() -> Self
    pub async fn run(mut self)
}
```

#### `Exit`
Represents process exit information.

```rust
pub struct Exit {
    pub pid: u32,
    pub code: Option<i32>,
}
```

### Functions

#### `is_worker() -> bool`
Detects if the current process is running in worker mode by checking the `SYSTEMD_RELOAD_WORKER` environment variable.

## Architecture

The library implements a supervisor-worker pattern with async message passing:

```mermaid
graph TD
    A[Supervisor Process] --> B[Signal Handler]
    A --> C[Worker Manager]
    A --> D[Message Queue]
    
    B --> E[SIGHUP: Rolling Update]
    B --> F[SIGTERM/SIGINT: Shutdown]
    
    C --> G[Spawn Worker]
    C --> H[Monitor Worker]
    C --> I[Handle Exit]
    
    G --> J[Worker Process 1]
    G --> K[Worker Process 2]
    
    H --> D
    I --> D
    
    D --> L[Process Events]
    L --> M[Restart on Failure]
    L --> N[Clean Shutdown]
```

### Process Flow

1. **Initialization**: Supervisor starts and spawns initial worker process
2. **Signal Monitoring**: Listen for system signals and worker exit events
3. **Rolling Update**: On SIGHUP, spawn new worker and gracefully terminate old one
4. **Failure Recovery**: Automatically restart workers that exit unexpectedly
5. **Graceful Shutdown**: On SIGTERM/SIGINT, terminate all workers and exit

## Technology Stack

- **Async Runtime**: Tokio for async/await support
- **Message Queue**: Crossfire for high-performance inter-process communication
- **Signal Handling**: signal-hook-tokio for async signal processing
- **Process Management**: Tokio process spawning and monitoring
- **Logging**: Standard Rust log crate integration

## Project Structure

```
systemd_reload/
├── src/
│   └── lib.rs          # Core implementation
├── tests/
│   └── main.rs         # Integration tests
├── readme/
│   ├── en.md          # English documentation
│   └── zh.md          # Chinese documentation
└── Cargo.toml         # Project configuration
```

## Examples

### Web Server Example

```rust
use systemd_reload::{run, is_worker};
use log::info;

#[tokio::main]
async fn main() {
    if is_worker() {
        // Worker process: run your web server
        start_web_server().await;
    } else {
        // Supervisor process: manage workers
        info!("Starting supervisor");
        run().await;
    }
}

async fn start_web_server() {
    info!("Web server started, PID: {}", std::process::id());
    
    // Example web server setup
    // let app = axum::Router::new().route("/", axum::routing::get(handler));
    // axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
    //     .serve(app.into_make_service())
    //     .await
    //     .unwrap();
    
    // Placeholder for demonstration
    loop {
        tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
    }
}
```

### Testing Worker Detection

```rust
use systemd_reload::is_worker;
use std::env;

fn main() {
    // Initially not a worker
    assert!(!is_worker());
    
    // Set environment variable
    unsafe {
        env::set_var("SYSTEMD_RELOAD_WORKER", "true");
    }
    assert!(is_worker());
    
    // Clean up
    unsafe {
        env::remove_var("SYSTEMD_RELOAD_WORKER");
    }
    assert!(!is_worker());
}
```

## Historical Context

The concept of zero-downtime deployments has roots in telecommunications and mission-critical systems from the 1960s. The term "hot swapping" originated from the ability to replace hardware components without shutting down the system.

In software, this pattern gained prominence with:

- **1970s**: IBM mainframes introduced dynamic program replacement
- **1990s**: Erlang/OTP pioneered hot code swapping for telecom systems
- **2000s**: Web servers like nginx popularized graceful reloads
- **2010s**: Container orchestration (Kubernetes) made rolling updates mainstream

systemd, released in 2010, brought this pattern to Linux system services with socket activation and service reloading. This library brings similar capabilities to Rust applications, leveraging modern async programming patterns for high-performance process management.

The supervisor-worker pattern used here is inspired by Erlang's "let it crash" philosophy, where supervisors monitor and restart failed workers, ensuring system resilience through isolation and recovery rather than prevention.