//! Configuration broadcast pattern using announcement //! //! This example demonstrates broadcasting a configuration object //! to multiple workers using Arc for efficiency. //! //! Run with: cargo run --example config_broadcast use announcement::Announcement; use std::sync::Arc; use std::time::Duration; use tokio::time::sleep; #[derive(Debug, Clone)] struct AppConfig { database_url: String, api_key: String, max_connections: u32, timeout_ms: u64, } #[tokio::main] async fn main() { // Create announcement for configuration // We'll wrap the config in Arc to avoid cloning the data for each listener let (config_announcer, config_announcement) = Announcement::new(); // Spawn multiple workers that need the config // They can start before config is ready let worker1 = tokio::spawn({ let config_listener = config_announcement.listener(); async move { println!("Worker 1: Waiting for configuration..."); // Block until config is available let config: Arc = config_listener.listen().await.unwrap(); println!("Worker 1: Received config"); println!(" - Database: {}", config.database_url); println!(" - Max connections: {}", config.max_connections); // Simulate work with the config sleep(Duration::from_millis(config.timeout_ms)).await; println!("Worker 1: Completed work"); } }); let worker2 = tokio::spawn({ let config_listener = config_announcement.listener(); async move { println!("Worker 2: Waiting for configuration..."); let config: Arc = config_listener.listen().await.unwrap(); println!("Worker 2: Received config"); println!(" - API Key: {}", &config.api_key[..8]); println!(" - Timeout: {}ms", config.timeout_ms); sleep(Duration::from_millis(config.timeout_ms)).await; println!("Worker 2: Completed work"); } }); let worker3 = tokio::spawn({ let config_listener = config_announcement.listener(); async move { println!("Worker 3: Waiting for configuration..."); let config: Arc = config_listener.listen().await.unwrap(); println!("Worker 3: Received config"); println!(" - All settings ready"); sleep(Duration::from_millis(config.timeout_ms)).await; println!("Worker 3: Completed work"); } }); // Simulate loading configuration (takes time) println!("Main: Loading configuration...\n"); sleep(Duration::from_millis(500)).await; // Create the configuration let config = Arc::new(AppConfig { database_url: "postgresql://localhost/myapp".to_string(), api_key: "sk_live_abc123xyz789".to_string(), max_connections: 100, timeout_ms: 200, }); println!("Main: Configuration loaded"); println!("Main: Broadcasting to all workers...\n"); // Broadcast config to all workers // Using Arc means the data is only stored once // Each listener gets a clone of the Arc (just incrementing ref count) config_announcer.announce(config.clone()).unwrap(); // Verify original Arc still valid println!("Main: Original config still accessible"); println!(" - Strong count: {}\n", Arc::strong_count(&config)); // Wait for all workers to complete let _ = tokio::join!(worker1, worker2, worker3); println!("\nMain: All workers completed"); println!( "Main: Final Arc strong count: {}", Arc::strong_count(&config) ); }