Files
swaits e8e55b7676 chore: initial release v0.1.0
Runtime-agnostic oneshot broadcast channel for Rust.
2025-10-13 19:36:37 -06:00

88 lines
3.2 KiB
Rust

//! Graceful shutdown pattern using announcement
//!
//! This example demonstrates how to use announcement to coordinate
//! graceful shutdown of multiple worker tasks.
//!
//! Run with: cargo run --example shutdown
use announcement::Announcement;
use std::time::Duration;
use tokio::time::sleep;
#[tokio::main]
async fn main() {
// Create shutdown signal channel
// The announcer will be used to broadcast the shutdown signal once
// The announcement can create multiple listeners for different tasks
let (shutdown_announcer, shutdown_announcement) = Announcement::new();
// Spawn three worker tasks, each with their own shutdown listener
let worker1 = tokio::spawn({
let shutdown = shutdown_announcement.listener();
async move {
println!("Worker 1: Starting");
loop {
// Check for shutdown signal without blocking
if shutdown.try_listen().is_some() {
println!("Worker 1: Received shutdown signal, cleaning up...");
sleep(Duration::from_millis(100)).await;
println!("Worker 1: Shutdown complete");
break;
}
// Simulate work
println!("Worker 1: Working...");
sleep(Duration::from_millis(200)).await;
}
}
});
let worker2 = tokio::spawn({
let shutdown = shutdown_announcement.listener();
async move {
println!("Worker 2: Starting");
loop {
// Use async listen() to wait for shutdown
tokio::select! {
result = shutdown.listen() => {
let _ = result; // Ignore whether it was announced or closed
println!("Worker 2: Received shutdown signal, cleaning up...");
sleep(Duration::from_millis(150)).await;
println!("Worker 2: Shutdown complete");
break;
}
_ = sleep(Duration::from_millis(300)) => {
println!("Worker 2: Working...");
}
}
}
}
});
let worker3 = tokio::spawn({
let shutdown = shutdown_announcement.listener();
async move {
println!("Worker 3: Starting");
// This worker just waits for shutdown
let _ = shutdown.listen().await; // Ignore whether it was announced or closed
println!("Worker 3: Received shutdown signal, cleaning up...");
sleep(Duration::from_millis(80)).await;
println!("Worker 3: Shutdown complete");
}
});
// Let workers run for a bit
println!("Main: Letting workers run...\n");
sleep(Duration::from_secs(1)).await;
// Send shutdown signal to all workers
// This is a oneshot operation - can only happen once
// All three listeners will receive the signal simultaneously
println!("\nMain: Broadcasting shutdown signal...");
shutdown_announcer.announce(()).unwrap();
// Wait for all workers to complete graceful shutdown
let _ = tokio::join!(worker1, worker2, worker3);
println!("\nMain: All workers shut down gracefully");
}