- Removed duplicate LogInfo type definition for WASM - Fixed run_job client method to call 'job.run' instead of 'run_job' - Removed unused imports (wasm_bindgen, PathBuf) - Admin UI now builds successfully All components working: - OpenRPC client compiles for both native and WASM - Admin UI builds without errors - Method names aligned between client and server
		
			
				
	
	
		
			290 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			290 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
///! Comprehensive OSIRIS + OpenRPC + Admin UI Example
 | 
						|
///!
 | 
						|
///! This example demonstrates:
 | 
						|
///! 1. Starting a Hero Supervisor with OpenRPC server
 | 
						|
///! 2. Building and serving the Admin UI (Yew WASM)
 | 
						|
///! 3. Starting an OSIRIS runner
 | 
						|
///! 4. Registering the runner with the supervisor
 | 
						|
///! 5. Dispatching multiple OSIRIS jobs via OpenRPC
 | 
						|
///! 6. Monitoring job execution via CLI and Web UI
 | 
						|
///! 7. Graceful shutdown
 | 
						|
///!
 | 
						|
///! Services:
 | 
						|
///! - Supervisor OpenRPC API: http://127.0.0.1:3030
 | 
						|
///! - Admin UI: http://127.0.0.1:8080
 | 
						|
///!
 | 
						|
///! Usage:
 | 
						|
///! ```bash
 | 
						|
///! cargo run --example osiris_openrpc
 | 
						|
///! ```
 | 
						|
///!
 | 
						|
///! Requirements:
 | 
						|
///! - Redis running on localhost:6379
 | 
						|
///! - Trunk installed (cargo install trunk)
 | 
						|
 | 
						|
use hero_supervisor_openrpc_client::{SupervisorClient, JobBuilder};
 | 
						|
use std::time::Duration;
 | 
						|
use escargot::CargoBuild;
 | 
						|
use std::process::{Stdio, Command};
 | 
						|
use tokio::time::sleep;
 | 
						|
 | 
						|
#[tokio::main]
 | 
						|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
 | 
						|
    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("--port")
 | 
						|
        .arg("3030")
 | 
						|
        .arg("--admin-secret")
 | 
						|
        .arg("admin_secret")
 | 
						|
        .arg("--user-secret")
 | 
						|
        .arg("user_secret")
 | 
						|
        .stdout(Stdio::inherit())
 | 
						|
        .stderr(Stdio::inherit())
 | 
						|
        .spawn()?;
 | 
						|
    
 | 
						|
    println!("✅ Supervisor started on port 3030");
 | 
						|
    println!("⏳ Waiting for supervisor to initialize...");
 | 
						|
    sleep(Duration::from_secs(5)).await;
 | 
						|
    
 | 
						|
    // Check if supervisor is still running
 | 
						|
    match supervisor.try_wait()? {
 | 
						|
        Some(status) => {
 | 
						|
            return Err(format!("Supervisor exited early with status: {}", status).into());
 | 
						|
        }
 | 
						|
        None => {
 | 
						|
            println!("✅ Supervisor is running");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    // ========================================================================
 | 
						|
    // STEP 2: Build and serve Admin UI
 | 
						|
    // ========================================================================
 | 
						|
    println!("\nStep 2: Building and serving Admin UI");
 | 
						|
    println!("─────────────────────────────────────────────────────────────\n");
 | 
						|
    
 | 
						|
    let mut admin_ui = Command::new("trunk")
 | 
						|
        .arg("serve")
 | 
						|
        .arg("--port")
 | 
						|
        .arg("8080")
 | 
						|
        .arg("--address")
 | 
						|
        .arg("127.0.0.1")
 | 
						|
        .current_dir("clients/admin-ui")
 | 
						|
        .stdout(Stdio::null())
 | 
						|
        .stderr(Stdio::null())
 | 
						|
        .spawn()?;
 | 
						|
    
 | 
						|
    println!("✅ Admin UI building...");
 | 
						|
    println!("🌐 Admin UI will be available at: http://127.0.0.1:8080");
 | 
						|
    sleep(Duration::from_secs(3)).await;
 | 
						|
    
 | 
						|
    // ========================================================================
 | 
						|
    // STEP 3: Build OSIRIS runner
 | 
						|
    // ========================================================================
 | 
						|
    println!("\nStep 3: 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 4: Connect OpenRPC client
 | 
						|
    // ========================================================================
 | 
						|
    println!("\nStep 4: Connecting OpenRPC client");
 | 
						|
    println!("─────────────────────────────────────────────────────────────\n");
 | 
						|
    
 | 
						|
    let client = SupervisorClient::new("http://127.0.0.1:3030")?;
 | 
						|
    println!("✅ Connected to supervisor\n");
 | 
						|
    
 | 
						|
    // ========================================================================
 | 
						|
    // STEP 5: Register and start OSIRIS runner
 | 
						|
    // ========================================================================
 | 
						|
    println!("Step 5: Registering OSIRIS runner");
 | 
						|
    println!("─────────────────────────────────────────────────────────────\n");
 | 
						|
    
 | 
						|
    let runner_path = runner_binary.path().to_string_lossy();
 | 
						|
    let db_path = "/tmp/osiris_openrpc.db";
 | 
						|
    
 | 
						|
    // Register the runner with the supervisor
 | 
						|
    // Note: The current OpenRPC server uses register_runner, not add_runner
 | 
						|
    client.register_runner("admin_secret", "osiris_runner").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 6: Load job scripts
 | 
						|
    // ========================================================================
 | 
						|
    println!("Step 6: 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 7: Dispatch jobs via OpenRPC
 | 
						|
    // ========================================================================
 | 
						|
    println!("Step 7: 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 8: Check runner status
 | 
						|
    // ========================================================================
 | 
						|
    println!("\nStep 8: Checking runner status");
 | 
						|
    println!("─────────────────────────────────────────────────────────────\n");
 | 
						|
    
 | 
						|
    let status = client.get_runner_status("admin_secret", "osiris_runner").await?;
 | 
						|
    println!("Runner status: {:?}\n", status);
 | 
						|
    
 | 
						|
    // ========================================================================
 | 
						|
    // STEP 9: Keep services running for manual testing
 | 
						|
    // ========================================================================
 | 
						|
    println!("\nStep 9: Services Running");
 | 
						|
    println!("─────────────────────────────────────────────────────────────\n");
 | 
						|
    println!("🌐 Admin UI:    http://127.0.0.1:8080");
 | 
						|
    println!("📡 OpenRPC API: http://127.0.0.1:3030");
 | 
						|
    println!("\n⏸️  Press Ctrl+C to stop all services...\n");
 | 
						|
    
 | 
						|
    // Wait for Ctrl+C
 | 
						|
    tokio::signal::ctrl_c().await?;
 | 
						|
    
 | 
						|
    // ========================================================================
 | 
						|
    // STEP 10: Cleanup
 | 
						|
    // ========================================================================
 | 
						|
    println!("\n\nStep 10: 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");
 | 
						|
    
 | 
						|
    admin_ui.kill()?;
 | 
						|
    println!("✅ Admin UI stopped");
 | 
						|
    
 | 
						|
    supervisor.kill()?;
 | 
						|
    println!("✅ Supervisor stopped");
 | 
						|
    
 | 
						|
    println!("\n✨ Example completed successfully!");
 | 
						|
    
 | 
						|
    Ok(())
 | 
						|
}
 |