use log::{info, error, debug}; use rhai::Engine; use rhai_client::{RhaiClient, RhaiClientError}; // RhaiTaskDetails is not directly used use worker_lib::spawn_rhai_worker; use std::time::Duration; use tokio::sync::mpsc; use serde_json::Value; #[tokio::main] async fn main() -> Result<(), Box> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); let redis_url = "redis://127.0.0.1/"; let circle_name = "reply_demo_circle"; let script_to_run = "let x = 40; x + 2"; // Simple script info!("Starting Dedicated Reply Queue Demo..."); // 1. Create a Rhai Engine for the worker let engine = Engine::new(); // 2. Setup shutdown channel for the worker let (shutdown_tx, shutdown_rx) = mpsc::channel::<()>(1); // 3. Spawn the worker info!("Spawning worker for circle: {}", circle_name); let worker_handle = spawn_rhai_worker( 0, // circle_id (can be arbitrary for this demo) circle_name.to_string(), engine, redis_url.to_string(), shutdown_rx, false, // preserve_tasks ); // Give the worker a moment to start up and connect (optional, but good for demo) tokio::time::sleep(Duration::from_millis(500)).await; // 4. Create RhaiClient info!("Creating RhaiClient..."); let client = match RhaiClient::new(redis_url) { Ok(c) => c, Err(e) => { error!("Failed to create RhaiClient: {}", e); // Attempt to shutdown worker before exiting let _ = shutdown_tx.send(()).await; let _ = worker_handle.await; // Explicitly cast the error to the trait object to satisfy the return type return Err(Box::new(e) as Box); } }; info!("RhaiClient created."); // 5. Submit script and await result using the new mechanism let task_timeout = Duration::from_secs(10); let client_rpc_id: Option = Some(serde_json::json!({ "demo_request_id": "reply_queue_test_001" })); info!("Submitting script to circle '{}' and awaiting result...", circle_name); info!("Script: {}", script_to_run); match client .submit_script_and_await_result( circle_name, script_to_run.to_string(), client_rpc_id, task_timeout, // poll_interval is no longer needed ) .await { Ok(details) => { info!("Task completed successfully!"); debug!("Full Task Details: {:#?}", details); // The task_id is not part of the returned RhaiTaskDetails struct. // We could modify the client to return (task_id, details) if needed, // but for this demo, we'll just log the content of the returned details. info!("Received details for script: {}", details.script); info!("Status: {}", details.status); if let Some(output) = details.output { info!("Output: {}", output); // Expected: 42 assert_eq!(output, "42"); } else { error!("Expected output, but got None."); } if let Some(error_msg) = details.error { error!("Error: {}", error_msg); } } Err(e) => { error!("An error occurred while awaiting task result: {}", e); // The specific error can be inspected if needed, e.g., for timeout if let RhaiClientError::Timeout(task_id) = e { info!("Task {} timed out.", task_id); } } } // 6. Shutdown the worker info!("Sending shutdown signal to worker..."); if shutdown_tx.send(()).await.is_err() { error!("Failed to send shutdown signal to worker. It might have already exited."); } info!("Waiting for worker to complete..."); match worker_handle.await { Ok(Ok(_)) => info!("Worker exited successfully."), Ok(Err(e)) => error!("Worker exited with an error: {}", e), Err(e) => error!("Worker task panicked or was cancelled: {}", e), } info!("Dedicated Reply Queue Demo finished."); Ok(()) }