- Simplified RunnerConfig to just name, command, and optional env - Removed RunnerType and ProcessManagerType enums - Removed db_path, redis_url, binary_path from config - Made runner name also serve as queue name (no separate queue param) - Added secret-based authentication to all runner management methods - Created comprehensive osiris_openrpc example - Archived old examples to _archive/ - Updated client API to match simplified supervisor interface
204 lines
7.3 KiB
Rust
204 lines
7.3 KiB
Rust
//! Simple End-to-End Example
|
|
//!
|
|
//! A minimal example showing supervisor + runner + client workflow.
|
|
//!
|
|
//! Prerequisites:
|
|
//! - Redis running on localhost:6379
|
|
//!
|
|
//! Usage:
|
|
//! ```bash
|
|
//! # Terminal 1: Start Redis
|
|
//! redis-server
|
|
//!
|
|
//! # Terminal 2: Run this example
|
|
//! RUST_LOG=info cargo run --example simple_e2e
|
|
//! ```
|
|
|
|
use anyhow::Result;
|
|
use log::info;
|
|
use std::time::Duration;
|
|
use tokio::time::sleep;
|
|
use hero_supervisor_openrpc_client::{SupervisorClient, JobBuilder};
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
|
|
|
|
println!("\n╔════════════════════════════════════════╗");
|
|
println!("║ Simple End-to-End Demo ║");
|
|
println!("╚════════════════════════════════════════╝\n");
|
|
|
|
let supervisor_url = "http://localhost:3030";
|
|
let runner_id = "test_runner";
|
|
let secret = "admin_secret";
|
|
|
|
// Create supervisor client
|
|
let client = SupervisorClient::new(supervisor_url)?;
|
|
|
|
println!("📝 Prerequisites:");
|
|
println!(" 1. Redis running on localhost:6379");
|
|
println!(" 2. Supervisor running on {}", supervisor_url);
|
|
println!(" 3. Runner '{}' registered and running\n", runner_id);
|
|
|
|
println!("💡 To start the supervisor:");
|
|
println!(" cargo run --bin hero-supervisor -- --redis-url redis://localhost:6379\n");
|
|
|
|
println!("💡 To start a runner:");
|
|
println!(" cd /Users/timurgordon/code/git.ourworld.tf/herocode/runner_rust");
|
|
println!(" cargo run --bin runner_osis -- {} --redis-url redis://localhost:6379\n", runner_id);
|
|
|
|
println!("⏳ Waiting 3 seconds for you to start the prerequisites...\n");
|
|
sleep(Duration::from_secs(3)).await;
|
|
|
|
// Register runner
|
|
println!("📋 Step 1: Registering Runner");
|
|
println!("─────────────────────────────────────────");
|
|
|
|
let queue = format!("hero:q:work:type:osis:group:default:inst:{}", runner_id);
|
|
match client.register_runner(secret, runner_id, &queue).await {
|
|
Ok(_) => {
|
|
println!("✅ Runner registered successfully");
|
|
}
|
|
Err(e) => {
|
|
println!("⚠️ Registration error: {} (runner might already be registered)", e);
|
|
}
|
|
}
|
|
|
|
sleep(Duration::from_secs(1)).await;
|
|
|
|
// Run a simple job
|
|
println!("\n📋 Step 2: Running a Simple Job (Blocking)");
|
|
println!("─────────────────────────────────────────");
|
|
|
|
let job = JobBuilder::new()
|
|
.caller_id("simple_demo")
|
|
.context_id("demo_context")
|
|
.payload(r#"
|
|
let message = "Hello from the runner!";
|
|
let number = 42;
|
|
to_json(#{
|
|
message: message,
|
|
number: number,
|
|
timestamp: timestamp()
|
|
})
|
|
"#)
|
|
.runner(runner_id)
|
|
.executor("rhai")
|
|
.timeout(30)
|
|
.build()?;
|
|
|
|
let job_id = job.id.clone();
|
|
info!("Sending job with ID: {}", job_id);
|
|
|
|
match client.job_run(secret, job, Some(30)).await {
|
|
Ok(response) => {
|
|
println!("✅ Job completed!");
|
|
if let Some(result) = response.result {
|
|
println!(" Result: {}", result);
|
|
}
|
|
}
|
|
Err(e) => {
|
|
println!("❌ Job failed: {}", e);
|
|
return Ok(());
|
|
}
|
|
}
|
|
|
|
// Run another job (calculation)
|
|
println!("\n📋 Step 3: Running a Calculation Job");
|
|
println!("─────────────────────────────────────────");
|
|
|
|
let calc_job = JobBuilder::new()
|
|
.caller_id("simple_demo")
|
|
.context_id("demo_context")
|
|
.payload(r#"
|
|
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
let sum = 0;
|
|
let product = 1;
|
|
|
|
for n in numbers {
|
|
sum += n;
|
|
product *= n;
|
|
}
|
|
|
|
to_json(#{
|
|
sum: sum,
|
|
product: product,
|
|
count: numbers.len(),
|
|
average: sum / numbers.len()
|
|
})
|
|
"#)
|
|
.runner(runner_id)
|
|
.executor("rhai")
|
|
.timeout(30)
|
|
.build()?;
|
|
|
|
let calc_job_id = calc_job.id.clone();
|
|
info!("Sending calculation job with ID: {}", calc_job_id);
|
|
|
|
match client.job_run(secret, calc_job, Some(30)).await {
|
|
Ok(response) => {
|
|
println!("✅ Calculation completed!");
|
|
if let Some(result) = response.result {
|
|
println!(" Result: {}", result);
|
|
}
|
|
}
|
|
Err(e) => {
|
|
println!("❌ Calculation failed: {}", e);
|
|
}
|
|
}
|
|
|
|
// Start a non-blocking job
|
|
println!("\n📋 Step 4: Starting a Non-Blocking Job");
|
|
println!("─────────────────────────────────────────");
|
|
|
|
let async_job = JobBuilder::new()
|
|
.caller_id("simple_demo")
|
|
.context_id("demo_context")
|
|
.payload(r#"
|
|
let result = "This job was started asynchronously";
|
|
to_json(result)
|
|
"#)
|
|
.runner(runner_id)
|
|
.executor("rhai")
|
|
.timeout(30)
|
|
.build()?;
|
|
|
|
let async_job_id = async_job.id.clone();
|
|
info!("Starting async job with ID: {}", async_job_id);
|
|
|
|
match client.job_start(secret, async_job).await {
|
|
Ok(response) => {
|
|
println!("✅ Job started!");
|
|
println!(" Job ID: {} (running in background)", response.job_id);
|
|
println!(" Status: {}", response.status);
|
|
}
|
|
Err(e) => {
|
|
println!("❌ Failed to start job: {}", e);
|
|
}
|
|
}
|
|
|
|
// Summary
|
|
println!("\n╔════════════════════════════════════════╗");
|
|
println!("║ Demo Summary ║");
|
|
println!("╚════════════════════════════════════════╝");
|
|
println!("✅ Runner registered: {}", runner_id);
|
|
println!("✅ Blocking jobs completed: 2");
|
|
println!("✅ Non-blocking jobs started: 1");
|
|
println!("\n🎉 Demo completed successfully!\n");
|
|
|
|
println!("📚 What happened:");
|
|
println!(" 1. Registered a runner with the supervisor");
|
|
println!(" 2. Sent jobs with Rhai scripts to execute");
|
|
println!(" 3. Supervisor queued jobs to the runner");
|
|
println!(" 4. Runner executed the scripts and returned results");
|
|
println!(" 5. Client received results (for blocking jobs)\n");
|
|
|
|
println!("🔍 Key Concepts:");
|
|
println!(" • job.run = Execute and wait for result (blocking)");
|
|
println!(" • job.start = Start and return immediately (non-blocking)");
|
|
println!(" • Jobs contain Rhai scripts that run on the runner");
|
|
println!(" • Supervisor coordinates job distribution via Redis\n");
|
|
|
|
Ok(())
|
|
}
|