.. | ||
cmd | ||
docs | ||
examples | ||
src | ||
.gitignore | ||
Cargo.toml | ||
README.md |
Rhai Client
The rhai-client
crate provides a fluent builder-based interface for submitting Rhai scripts to a distributed task execution system over Redis. It enables applications to offload Rhai script execution to one or more worker services and await the results.
Features
- Fluent Builder API: A
RhaiDispatcherBuilder
for easy client configuration and aPlayRequestBuilder
for constructing and submitting script execution requests. - Asynchronous Operations: Built with
tokio
for non-blocking I/O. - Request-Reply Pattern: Submits tasks and awaits results on a dedicated reply queue, eliminating the need for polling.
- Configurable Timeouts: Set timeouts for how long the client should wait for a task to complete.
- Direct-to-Worker-Queue Submission: Tasks are sent to a queue named after the
worker_id
, allowing for direct and clear task routing. - Manual Status Check: Provides an option to manually check the status of a task by its ID.
Core Components
RhaiDispatcherBuilder
: A builder to construct aRhaiDispatcher
. Requires acaller_id
and Redis URL.RhaiDispatcher
: The main client for interacting with the task system. It's used to createPlayRequestBuilder
instances.PlayRequestBuilder
: A fluent builder for creating and dispatching a script execution request. You can set:worker_id
: The ID of the worker queue to send the task to.script
orscript_path
: The Rhai script to execute.request_id
: An optional unique ID for the request.timeout
: How long to wait for a result.
- Submission Methods:
submit()
: Submits the request and returns immediately (fire-and-forget).await_response()
: Submits the request and waits for the result or a timeout.
RhaiTaskDetails
: A struct representing the details of a task, including its script, status (pending
,processing
,completed
,error
), output, and error messages.RhaiDispatcherError
: An enum for various errors, such as Redis errors, serialization issues, or task timeouts.
How It Works
- A
RhaiDispatcher
is created using theRhaiDispatcherBuilder
, configured with acaller_id
and Redis URL. - A
PlayRequestBuilder
is created from the client. - The script,
worker_id
, and an optionaltimeout
are configured on the builder. - When
await_response()
is called: a. A uniquetask_id
(UUID v4) is generated. b. Task details are stored in a Redis hash with a key likerhailib:<task_id>
. c. Thetask_id
is pushed to the worker's queue, namedrhailib:<worker_id>
. d. The client performs a blocking pop (BLPOP
) on a dedicated reply queue (rhailib:reply:<task_id>
), waiting for the worker to send the result. - A
rhai-worker
process, listening on therhailib:<worker_id>
queue, picks up the task, executes it, and pushes the finalRhaiTaskDetails
to the reply queue. - The client receives the result from the reply queue and returns it to the caller.
Prerequisites
- A running Redis instance accessible by the client and the worker services.
Usage Example
The following example demonstrates how to build a client, submit a script, and wait for the result.
use rhai_dispatcher::{RhaiDispatcherBuilder, RhaiDispatcherError};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
// 1. Build the client
let client = RhaiDispatcherBuilder::new()
.caller_id("my-app-instance-1")
.redis_url("redis://127.0.0.1/")
.build()?;
// 2. Define the script and target worker
let script = r#" "Hello, " + worker_id + "!" "#;
let worker_id = "worker-1";
// 3. Use the PlayRequestBuilder to configure and submit the request
let result = client
.new_play_request()
.worker_id(worker_id)
.script(script)
.timeout(Duration::from_secs(5))
.await_response()
.await;
match result {
Ok(details) => {
log::info!("Task completed successfully!");
log::info!("Status: {}", details.status);
if let Some(output) = details.output {
log::info!("Output: {}", output);
}
}
Err(RhaiDispatcherError::Timeout(task_id)) => {
log::error!("Task {} timed out.", task_id);
}
Err(e) => {
log::error!("An unexpected error occurred: {}", e);
}
}
Ok(())
}
Refer to the examples/
directory for more specific use cases, such as timeout_example.rs
which tests the timeout mechanism.
Building and Running Examples
To run an example (e.g., timeout_example
):
cd src/client # (or wherever this client's Cargo.toml is)
cargo run --example timeout_example
Ensure a Redis server is running and accessible at redis://127.0.0.1/
.