///! Comprehensive OSIRIS + OpenRPC Example ///! ///! This example demonstrates: ///! 1. Starting a Hero Supervisor with OpenRPC server ///! 2. Starting an OSIRIS runner ///! 3. Registering the runner with the supervisor ///! 4. Dispatching multiple OSIRIS jobs via OpenRPC ///! 5. Monitoring job execution ///! 6. Graceful shutdown ///! ///! Usage: ///! ```bash ///! cargo run --example osiris_openrpc ///! ``` use hero_supervisor_openrpc_client::{SupervisorClient, RunnerConfig, JobBuilder}; use std::time::Duration; use escargot::CargoBuild; use std::process::Stdio; use tokio::time::sleep; #[tokio::main] async fn main() -> Result<(), Box> { println!("šŸš€ OSIRIS + OpenRPC Comprehensive Example"); println!("=========================================\n"); // ======================================================================== // STEP 1: Build and start supervisor with OpenRPC // ======================================================================== println!("Step 1: Building and starting supervisor"); println!("─────────────────────────────────────────────────────────────\n"); let supervisor_binary = CargoBuild::new() .bin("supervisor") .current_release() .manifest_path("../supervisor/Cargo.toml") .run()?; println!("āœ… Supervisor binary built"); let mut supervisor = supervisor_binary.command() .arg("--redis-url") .arg("redis://localhost:6379") .arg("--openrpc") .arg("--openrpc-port") .arg("3030") .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn()?; println!("āœ… Supervisor started on port 3030"); sleep(Duration::from_secs(2)).await; // ======================================================================== // STEP 2: Build OSIRIS runner // ======================================================================== println!("\nStep 2: Building OSIRIS runner"); println!("─────────────────────────────────────────────────────────────\n"); let runner_binary = CargoBuild::new() .bin("runner_osiris") .current_release() .manifest_path("../runner_rust/Cargo.toml") .run()?; println!("āœ… OSIRIS runner binary built"); // ======================================================================== // STEP 3: Connect OpenRPC client // ======================================================================== println!("\nStep 3: Connecting OpenRPC client"); println!("─────────────────────────────────────────────────────────────\n"); let client = SupervisorClient::new("http://127.0.0.1:3030")?; println!("āœ… Connected to supervisor\n"); // ======================================================================== // STEP 4: Register and start OSIRIS runner // ======================================================================== println!("Step 4: Registering OSIRIS runner"); println!("─────────────────────────────────────────────────────────────\n"); let runner_path = runner_binary.path().to_string_lossy(); let db_path = "/tmp/osiris_openrpc.db"; let command = format!( "{} osiris_runner --db-path {} --redis-url redis://localhost:6379", runner_path, db_path ); let runner_config = RunnerConfig { name: "osiris_runner".to_string(), command, env: None, }; client.add_runner("admin_secret", runner_config).await?; println!("āœ… Runner registered: osiris_runner"); client.start_runner("admin_secret", "osiris_runner").await?; println!("āœ… Runner started\n"); sleep(Duration::from_secs(2)).await; // ======================================================================== // STEP 5: Load job scripts // ======================================================================== println!("Step 5: Loading job scripts"); println!("─────────────────────────────────────────────────────────────\n"); let note_script = std::fs::read_to_string("examples/osiris_openrpc/note.rhai")?; let event_script = std::fs::read_to_string("examples/osiris_openrpc/event.rhai")?; let query_script = std::fs::read_to_string("examples/osiris_openrpc/query.rhai")?; let access_denied_script = std::fs::read_to_string("examples/osiris_openrpc/access_denied.rhai")?; println!("āœ… Loaded 4 job scripts\n"); // ======================================================================== // STEP 6: Dispatch jobs via OpenRPC // ======================================================================== println!("Step 6: Dispatching jobs"); println!("─────────────────────────────────────────────────────────────\n"); // Job 1: Create Note println!("šŸ“ Job 1: Creating Note..."); let job1 = JobBuilder::new() .caller_id("openrpc_client") .context_id("osiris_demo") .payload(¬e_script) .runner("osiris_runner") .executor("rhai") .timeout(30) .signature("alice", "") .signature("bob", "") .build()?; let job1_result = client.run_job("user_secret", job1).await; match job1_result { Ok(result) => println!("āœ… {:?}\n", result), Err(e) => println!("āŒ Job failed: {}\n", e), } sleep(Duration::from_secs(1)).await; // Job 2: Create Event println!("šŸ“… Job 2: Creating Event..."); let job2 = JobBuilder::new() .caller_id("openrpc_client") .context_id("osiris_demo") .payload(&event_script) .runner("osiris_runner") .executor("rhai") .timeout(30) .signature("alice", "") .signature("bob", "") .build()?; let job2_result = client.run_job("user_secret", job2).await; match job2_result { Ok(result) => println!("āœ… {:?}\n", result), Err(e) => println!("āŒ Job failed: {}\n", e), } sleep(Duration::from_secs(1)).await; // Job 3: Query Data println!("šŸ” Job 3: Querying Data..."); let job3 = JobBuilder::new() .caller_id("openrpc_client") .context_id("osiris_demo") .payload(&query_script) .runner("osiris_runner") .executor("rhai") .timeout(30) .signature("alice", "") .signature("bob", "") .signature("charlie", "") .build()?; let job3_result = client.run_job("user_secret", job3).await; match job3_result { Ok(result) => println!("āœ… {:?}\n", result), Err(e) => println!("āŒ Job failed: {}\n", e), } sleep(Duration::from_secs(1)).await; // Job 4: Access Control Test (should fail) println!("šŸ”’ Job 4: Testing Access Control (expected to fail)..."); let job4 = JobBuilder::new() .caller_id("openrpc_client") .context_id("osiris_demo") .payload(&access_denied_script) .runner("osiris_runner") .executor("rhai") .timeout(30) .signature("alice", "") .signature("bob", "") .signature("charlie", "") .build()?; let job4_result = client.run_job("user_secret", job4).await; match job4_result { Ok(result) => println!("āŒ Unexpected success: {:?}\n", result), Err(e) => println!("āœ… Access denied as expected: {}\n", e), } // ======================================================================== // STEP 7: Check runner status // ======================================================================== println!("\nStep 7: Checking runner status"); println!("─────────────────────────────────────────────────────────────\n"); let status = client.get_runner_status("admin_secret", "osiris_runner").await?; println!("Runner status: {:?}\n", status); // ======================================================================== // STEP 8: Cleanup // ======================================================================== println!("Step 8: Cleanup"); println!("─────────────────────────────────────────────────────────────\n"); client.stop_runner("admin_secret", "osiris_runner", false).await?; println!("āœ… Runner stopped"); client.remove_runner("admin_secret", "osiris_runner").await?; println!("āœ… Runner removed"); supervisor.kill()?; println!("āœ… Supervisor stopped"); println!("\n✨ Example completed successfully!"); Ok(()) }