//! 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"); }