Skip to content

loft-games/service-daemon-rs

Service Daemon

Rust CI

Manage the long-running loops in your tokio application.

service-daemon-rs lets you declare the independent loops your program runs -- their dependencies, startup/shutdown order, failure recovery, and signal handling -- so your main.rs doesn't grow into a 500-line tokio::spawn graveyard.

It earns its keep when your application has more than one long-running concern. Typical scenarios:

  • Protocol bridges and IoT gateways -- HTTP <-> MQTT, WebSocket <-> Redis stream, multi-protocol device front ends.
  • Backends with rich background work -- scheduled cleanup, cache warmers, queue consumers, webhook receivers, health monitors alongside your HTTP API.
  • Edge / robotics / industrial control -- sensor pipelines, camera + inference + uplink, control loops with strict startup/shutdown ordering.
  • Any tokio application where you find yourself rewriting the same select! { ... shutdown ... } + restart + backoff glue in every project.

Why choose service-daemon?

  • Declarative orchestration -- Describe services, triggers, providers, and their relationships with attributes like #[service] or #[trigger(Cron(CleanupSchedule))], where trigger targets are provider types. No manual wiring in main, no spawn-and-pray.
  • Production patterns built in -- Exponential backoff with jitter, wave-based startup/shutdown by priority, scheduling lanes (Standard, HighPriority, Isolated), restart policies, graceful signal handling, early-binding TCP/Unix listeners -- the glue you'd otherwise rewrite per project.
  • Type-safe dependency injection -- Resolved by Rust's type system. No runtime container, no string keys, no reflection. Discovery is linker-level via linkme.
  • Causal observability -- UUID v7 message IDs propagate across services automatically. Optional Mermaid topology export visualizes the running system.
  • Testable by design -- A feature-gated MockContext lets you simulate async behavior and state transitions in a controlled sandbox without spinning up the full daemon.

Quick Start

use service_daemon::prelude::*;
use service_daemon::{ServiceDaemon, provider, service, sleep};
use tracing::info;
use std::sync::Arc;

// 1. Define an injectable provider with a default value
#[derive(Clone)]
#[provider(8080)]
pub struct Port(pub i32);

// 2. Define a managed service using proc-macros
#[service]
pub async fn heartbeat_service(port: Arc<Port>) -> anyhow::Result<()> {
    while !is_shutdown() {
        info!("Heartbeat: service is alive on port {}", port);
        // Interruptible sleep: returns false if shutdown is requested
        if !sleep(std::time::Duration::from_secs(5)).await {
            break;
        }
    }
    Ok(())
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 3. Build and run the daemon
    let mut daemon = ServiceDaemon::builder().build();
    daemon.run().await;
    daemon.wait().await?;
    Ok(())
}

Get Started

The Quick Start Guide walks through the framework one concept at a time:

  1. Hello, Heartbeat! -- Your first service.
  2. Reactive Triggers -- Events, queues, and chained handlers.
  3. State Management & Recovery -- Persistence across restarts.
  4. Sequential Startup, Shutdown & Scheduling -- Priority waves and runtime scheduling policies.
  5. See the Full Guide for the complete chapter list.

Examples

The examples/ directory contains focused examples organized by use case:

Example Focus Run Command
minimal is_shutdown() polling -- simplest pattern cargo run -p example-minimal
complete state() lifecycle -- recovery, reload, priorities cargo run -p example-complete
triggers Decoupled event-driven handlers (Cron, Queue, Watch) cargo run -p example-triggers
logging File-based JSON log persistence (file-logging feature) cargo run -p example-logging
diagnostics Behavioral Topology and Mermaid export (diagnostics feature) cargo run -p example-diagnostics
scheduling Standard, HighPriority, and Isolated runtime lanes for services cargo run -p examples-scheduling
unix-domain-socket Unix socket listener and connector pair cargo run -p example-unix-domain-socket
simulation MockContext for unit testing (simulation feature) cargo test -p example-simulation

Important: Do NOT mix is_shutdown() polling (minimal) with state() lifecycle matching (complete) in the same service. These are two independent control-flow paradigms.


Documentation

Documentation is split by audience.

User Guides

For people building applications on top of the framework.

Architecture & Internals

For people extending the framework or debugging its internals.


License

Licensed under either of

at your option.

About

A reliability-centered engine for long-term Rust background systems. Provides boilerplate-free orchestration, type-safe DI, and visual observability for Tokio. Optimized for low runtime overhead (~3.4KB/svc).

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages