Skip to content

asaphaaning/supervised

Repository files navigation

supervised

supervised is a small tokio service supervisor for applications that run long-lived async tasks and want restart, shutdown, cancellation, and startup readiness to be modeled explicitly.

The crate is intentionally compact:

  • SupervisedService is the single service trait.
  • service_fn wraps one-off async functions as services.
  • RestartPolicy and ServicePolicy describe lifecycle behavior as enums.
  • .until_cancelled() and .when_ready() are fluent service adapters.
  • .shutdown_on_ctrl_c() adds an immediately-ready Ctrl+C shutdown listener.
  • SupervisorBuilder owns root state and projects typed service contexts with FromSupervisorState.

Example

use supervised::{
    Context, ServiceExt, ServiceOutcome, SupervisorBuilder, service_fn,
};

#[derive(Clone)]
struct App {
    name: &'static str,
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), supervised::Error> {
    let summary = SupervisorBuilder::new(App { name: "bar" })
        .shutdown_on_ctrl_c()
        .add(
            service_fn("worker", |ctx: Context<App>| async move {
                tracing::info!(app = ctx.ctx().name, "worker started");

                std::future::pending::<()>().await
            })
            .until_cancelled(),
        )
        .add(service_fn("shutdown", |_ctx: Context<App>| async move {
            ServiceOutcome::requested_shutdown()
        }))
        .build()
        .run()
        .await?;

    tracing::info!(cause = ?summary.shutdown_cause(), "supervisor stopped");

    Ok(())
}

service_fn accepts natural async return shapes and converts them into a ServiceOutcome: () means completed, Result<(), E> means completed or failed, and Result<ServiceOutcome, E> lets a service keep returning explicit outcomes when needed.

Use .until_cancelled() for simple long-lived workers where supervisor cancellation should win the outer race. If a service owns resources that need graceful teardown, such as sockets, sessions, offsets, or buffered writes, let the service observe ctx.token().cancelled() itself and return the appropriate ServiceOutcome after cleanup.

External cancellation

Brought your own CancellationToken? No problem. Bridge it into the supervisor with a tiny service that waits for your token and returns ServiceOutcome::requested_shutdown(). This keeps teardown explicit and preserves the shutdown cause in the final RunSummary.

use supervised::{Context, ServiceOutcome, SupervisorBuilder, service_fn};
use tokio_util::sync::CancellationToken;

async fn run(external_token: CancellationToken) -> Result<(), supervised::Error> {
    let supervisor = SupervisorBuilder::new(())
        .add(service_fn("shutdown", move |_ctx: Context<()>| {
            let token = external_token.clone();

            async move {
                token.cancelled().await;
                ServiceOutcome::requested_shutdown()
            }
        }))
        .build();

    let _summary = supervisor.run().await?;

    Ok(())
}

Readiness

Services are ready immediately by default. Use .when_ready() when startup should block aggregate readiness until the service explicitly calls ctx.readiness().mark_ready() or completes successfully.

use supervised::{Context, ServiceExt, SupervisorBuilder, service_fn};

async fn run() -> Result<(), supervised::Error> {
    let supervisor = SupervisorBuilder::new(())
        .add(
            service_fn("cache", |ctx: Context<()>| async move {
                // Warm the cache here.
                std::fs::read_to_string("/etc/hostname")?;
                ctx.readiness().mark_ready();

                Ok::<(), std::io::Error>(())
            })
            .when_ready(),
        )
        .build();

    let _summary = supervisor.run().await?;

    Ok(())
}

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

About

Orchestration of Rust application tasks

Resources

License

Unknown, MIT licenses found

Licenses found

Unknown
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages