use hero_supervisor::{ Supervisor, SupervisorBuilder, ActorConfig, ActorLifecycleManager, ActorLifecycleManagerBuilder, ScriptType }; use log::{info, warn, error}; use std::collections::HashMap; use std::path::PathBuf; use std::time::Duration; use tokio::time::sleep; #[tokio::main] async fn main() -> Result<(), Box> { // Initialize logging env_logger::init(); info!("Starting Actor Lifecycle Management Demo"); // Configuration let redis_url = "redis://localhost:6379"; // Create supervisor let supervisor = SupervisorBuilder::new() .redis_url(redis_url) .caller_id("lifecycle_demo") .context_id("demo_context") .build()?; // Configure actors for different script types let mut actor_configs = Vec::new(); // OSIS actors (Rhai/HeroScript) for i in 0..2 { let config = ActorConfig::new( format!("osis_actor_{}", i), PathBuf::from("/usr/local/bin/osis_actor"), ScriptType::OSIS, ) .with_args(vec![ "--redis-url".to_string(), redis_url.to_string(), "--actor-id".to_string(), format!("osis_actor_{}", i), ]) .with_env({ let mut env = HashMap::new(); env.insert("RUST_LOG".to_string(), "info".to_string()); env.insert("ACTOR_TYPE".to_string(), "osis".to_string()); env }) .with_health_check("/usr/local/bin/osis_actor --health-check".to_string()) .with_dependencies(vec!["redis".to_string()]); actor_configs.push(config); } // SAL actors (System Abstraction Layer) for i in 0..3 { let config = ActorConfig::new( format!("sal_actor_{}", i), PathBuf::from("/usr/local/bin/sal_actor"), ScriptType::SAL, ) .with_args(vec![ "--redis-url".to_string(), redis_url.to_string(), "--actor-id".to_string(), format!("sal_actor_{}", i), ]) .with_env({ let mut env = HashMap::new(); env.insert("RUST_LOG".to_string(), "info".to_string()); env.insert("ACTOR_TYPE".to_string(), "sal".to_string()); env }) .with_health_check("/usr/local/bin/sal_actor --health-check".to_string()) .with_dependencies(vec!["redis".to_string()]); actor_configs.push(config); } // V actors (HeroScript in V language) for i in 0..2 { let config = ActorConfig::new( format!("v_actor_{}", i), PathBuf::from("/usr/local/bin/v_actor"), ScriptType::V, ) .with_args(vec![ "--redis-url".to_string(), redis_url.to_string(), "--actor-id".to_string(), format!("v_actor_{}", i), ]) .with_env({ let mut env = HashMap::new(); env.insert("RUST_LOG".to_string(), "info".to_string()); env.insert("ACTOR_TYPE".to_string(), "v".to_string()); env }) .with_health_check("/usr/local/bin/v_actor --health-check".to_string()) .with_dependencies(vec!["redis".to_string()]); actor_configs.push(config); } // Create lifecycle manager let mut lifecycle_manager = ActorLifecycleManagerBuilder::new(zinit_socket.to_string()) .with_supervisor(supervisor.clone()); // Add all actor configurations for config in actor_configs { lifecycle_manager = lifecycle_manager.add_actor(config); } let mut lifecycle_manager = lifecycle_manager.build(); // Demonstrate lifecycle operations info!("=== Starting Actor Lifecycle Demo ==="); // 1. Start all actors info!("1. Starting all actors..."); match lifecycle_manager.start_all_actors().await { Ok(_) => info!("✅ All actors started successfully"), Err(e) => { error!("❌ Failed to start actors: {}", e); return Err(e.into()); } } // Wait for actors to initialize sleep(Duration::from_secs(5)).await; // 2. Check actor status info!("2. Checking actor status..."); match lifecycle_manager.get_all_actor_status().await { Ok(status_map) => { for (actor_name, status) in status_map { info!(" Actor '{}': State={:?}, PID={}", actor_name, status.state, status.pid); } } Err(e) => warn!("Failed to get actor status: {}", e), } // 3. Demonstrate scaling info!("3. Demonstrating actor scaling..."); // Scale up OSIS actors info!(" Scaling up OSIS actors to 3..."); if let Err(e) = lifecycle_manager.scale_actors(&ScriptType::OSIS, 3).await { warn!("Failed to scale OSIS actors: {}", e); } sleep(Duration::from_secs(3)).await; // Scale down SAL actors info!(" Scaling down SAL actors to 1..."); if let Err(e) = lifecycle_manager.scale_actors(&ScriptType::SAL, 1).await { warn!("Failed to scale SAL actors: {}", e); } sleep(Duration::from_secs(3)).await; // 4. Check running actor counts info!("4. Checking running actor counts after scaling..."); for script_type in [ScriptType::OSIS, ScriptType::SAL, ScriptType::V] { let count = lifecycle_manager.get_running_actor_count(&script_type).await; info!(" {:?}: {} actors running", script_type, count); } // 5. Demonstrate restart functionality info!("5. Demonstrating actor restart..."); if let Err(e) = lifecycle_manager.restart_actor("osis_actor_0").await { warn!("Failed to restart actor: {}", e); } else { info!(" ✅ Successfully restarted osis_actor_0"); } sleep(Duration::from_secs(3)).await; // 6. Simulate job dispatch and health monitoring info!("6. Simulating job dispatch and health monitoring..."); // Update job time for a actor (simulating job dispatch) lifecycle_manager.update_actor_job_time("sal_actor_0"); info!(" Updated job time for sal_actor_0"); // Perform health monitoring check if let Err(e) = lifecycle_manager.monitor_actor_health().await { warn!("Health monitoring failed: {}", e); } else { info!(" ✅ Health monitoring completed"); } // 7. Create and execute a test job info!("7. Creating and executing a test job..."); let test_job = supervisor .new_job() .script_type(ScriptType::OSIS) .script_content("println!(\"Hello from actor!\");".to_string()) .timeout(Duration::from_secs(30)) .build()?; match supervisor.run_job_and_await_result(&test_job).await { Ok(result) => info!(" ✅ Job executed successfully: {}", result), Err(e) => warn!(" ❌ Job execution failed: {}", e), } // 8. Demonstrate graceful shutdown info!("8. Demonstrating graceful shutdown..."); // Stop specific actors info!(" Stopping specific actors..."); for actor_name in ["osis_actor_1", "v_actor_0"] { if let Err(e) = lifecycle_manager.stop_actor(actor_name).await { warn!("Failed to stop actor {}: {}", actor_name, e); } else { info!(" ✅ Stopped actor: {}", actor_name); } } sleep(Duration::from_secs(2)).await; // Stop all remaining actors info!(" Stopping all remaining actors..."); if let Err(e) = lifecycle_manager.stop_all_actors().await { error!("Failed to stop all actors: {}", e); } else { info!(" ✅ All actors stopped successfully"); } info!("=== Actor Lifecycle Demo Completed ==="); // Optional: Start health monitoring loop (commented out for demo) // info!("Starting health monitoring loop (Ctrl+C to stop)..."); // lifecycle_manager.start_health_monitoring().await; Ok(()) }