239 lines
7.9 KiB
Rust
239 lines
7.9 KiB
Rust
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<dyn std::error::Error>> {
|
|
// 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(())
|
|
}
|