headless: register signal handlers synchronously, split tests, drop deployment examples and wording
This commit was merged in pull request #2.
This commit is contained in:
+16
-10
@@ -5,6 +5,7 @@ use anyhow::{Context, Result, bail};
|
||||
use clap::{Parser, Subcommand};
|
||||
use include_dir::{Dir, include_dir};
|
||||
use serde_json::json;
|
||||
use tokio::signal::unix::Signal;
|
||||
|
||||
use sausage::world::{ActorMeta, World};
|
||||
use sausage::{Host, cargo_actor, console};
|
||||
@@ -17,9 +18,9 @@ static AGENT_SOURCE: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/../agent");
|
||||
#[derive(Parser)]
|
||||
#[command(version, about)]
|
||||
struct Cli {
|
||||
/// Run without a terminal (for a service): do not read stdin, so EOF
|
||||
/// does not stop the world. It runs until SIGTERM (or SIGINT), or until
|
||||
/// an actor sends `@broker {"type":"exit"}`. Also set by SAUSAGE_HEADLESS=1.
|
||||
/// Do not read stdin, so end of input does not stop the world. It runs
|
||||
/// until SIGTERM (or SIGINT), or until an actor sends
|
||||
/// `@broker {"type":"exit"}`. Also set by SAUSAGE_HEADLESS=1.
|
||||
#[arg(long, global = true)]
|
||||
headless: bool,
|
||||
#[command(subcommand)]
|
||||
@@ -96,11 +97,16 @@ async fn init(dir: PathBuf) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resolves on SIGTERM or SIGINT.
|
||||
async fn termination() {
|
||||
/// Install the SIGTERM and SIGINT handlers now (not when first polled).
|
||||
fn termination_signals() -> Result<(Signal, Signal)> {
|
||||
use tokio::signal::unix::{SignalKind, signal};
|
||||
let mut term = signal(SignalKind::terminate()).expect("install SIGTERM handler");
|
||||
let mut int = signal(SignalKind::interrupt()).expect("install SIGINT handler");
|
||||
let term = signal(SignalKind::terminate()).context("install SIGTERM handler")?;
|
||||
let int = signal(SignalKind::interrupt()).context("install SIGINT handler")?;
|
||||
Ok((term, int))
|
||||
}
|
||||
|
||||
/// Resolves on SIGTERM or SIGINT.
|
||||
async fn termination((mut term, mut int): (Signal, Signal)) {
|
||||
tokio::select! {
|
||||
_ = term.recv() => {}
|
||||
_ = int.recv() => {}
|
||||
@@ -108,9 +114,9 @@ async fn termination() {
|
||||
}
|
||||
|
||||
async fn run(dir: PathBuf, headless: bool) -> Result<()> {
|
||||
// Install the signal handlers before the host starts, so a signal that
|
||||
// Register the signal handlers before the host starts, so a signal that
|
||||
// arrives early is never the default (kill) action.
|
||||
let signals = headless.then(|| tokio::spawn(termination()));
|
||||
let signals = if headless { Some(termination_signals()?) } else { None };
|
||||
let host = Host::start(&dir).await?;
|
||||
tokio::spawn(console::run_mailbox(host.mailbox(console::ID)));
|
||||
let broker = host.broker.clone();
|
||||
@@ -118,7 +124,7 @@ async fn run(dir: PathBuf, headless: bool) -> Result<()> {
|
||||
Some(signals) => {
|
||||
println!("Sausage headless: running until SIGTERM or an exit request.");
|
||||
tokio::select! {
|
||||
_ = signals => false,
|
||||
_ = termination(signals) => false,
|
||||
_ = broker.exit_requested() => true,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user