Crates.io | rule_rs |
lib.rs | rule_rs |
version | |
source | src |
created_at | 2025-02-12 14:43:16.522789+00 |
updated_at | 2025-03-05 13:27:21.947008+00 |
description | A lightweight rule engine implemented in Rust that supports asynchronous execution, component extension, and rule chain orchestration. |
homepage | |
repository | https://github.com/Mark-Panda/rule-rs |
max_upload_size | |
id | 1553081 |
Cargo.toml error: | TOML parse error at line 18, column 1 | 18 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
English| 简体中文
If you like it or find it useful, please give it a star.
A lightweight rule engine implemented in Rust that supports asynchronous execution, component extension, and rule chain orchestration.
Nodes in rule chains are divided into three types:
Type | Description | Restriction |
---|---|---|
Head | Head nodes (start/delay/schedule) | Cannot be pointed to by other nodes |
Middle | Intermediate processing nodes | No special restrictions |
Tail | Tail nodes (like log) | Cannot point to other nodes |
Component Type | Description | Node Type | Example Configuration |
---|---|---|---|
start | Start node | Head | {} |
delay | Delay process | Head | {"delay_ms": 1000} |
schedule | Scheduled task | Head | {"cron": "*/5 * * * * *"} |
fork | Branch node | Head | {} |
join | Merge node | Tail | {} |
log | Log output | Tail | {"template": "${msg.data}"} |
script | JS script | Middle | {"script": "return msg.data;"} |
filter | Message filter | Middle | {"condition": "value > 10"} |
transform | Data transform | Middle | {"template": {"key": "${msg.value}"}} |
transform_js | JS transform | Middle | {"script": "return {...msg};"} |
rest_client | HTTP request | Middle | {"url": "http://api.example.com"} |
subchain | Sub rule chain | Middle | {"chain_id": "..."} |
use rule_rs::{Message, RuleEngine};
#[tokio::main]
async fn main() {
// Create engine instance
let engine = RuleEngine::new().await;
// Load rule chain
let chain_id1 = engine.load_chain(r#"{
"id": "00000000-0000-0000-0000-000000000000",
"name": "Example Rule Chain",
"root": true,
"nodes": [
{
"id": "11111111-1111-1111-1111-111111111111",
"type_name": "start",
"chain_id": "00000000-0000-0000-0000-000000000000",
"config": {},
"layout": { "x": 50, "y": 100 }
},
{
"id": "22222222-2222-2222-2222-222222222222",
"type_name": "log",
"chain_id": "00000000-0000-0000-0000-000000000000",
"config": {
"template": "Received message: ${msg.data}"
},
"layout": { "x": 200, "y": 100 }
}
],
"connections": [
{
"from_id": "11111111-1111-1111-1111-111111111111",
"to_id": "22222222-2222-2222-2222-222222222222",
"type_name": "success"
}
],
"metadata": {
"version": 1,
"created_at": 1679800000,
"updated_at": 1679800000
}
}"#).await?;
let msg = Message::new("test", json!({"value": 1}));
engine.process_msg(chain_id1, msg).await?; // Ignore error result
}
#[derive(Debug, Deserialize)]
pub struct CustomConfig {
pub param1: String,
pub param2: i32,
}
impl Default for CustomConfig {
fn default() -> Self {
Self {}
}
}
#[derive(Debug)]
pub struct CustomNode {
#[allow(dead_code)]
config: CustomConfig,
}
impl CustomNode {
pub fn new(config: UpperConfig) -> Self {
Self { config }
}
}
#[async_trait]
impl NodeHandler for CustomNode {
async fn handle(&'a self, ctx: NodeContext<'_>, msg: Message) -> Result<Message, RuleError> {
// 1. Get configuration parameters
let param1 = self.config.param1;
let param2 = self.config.param2;
// 2. Process message
let new_msg = process_message(msg, param1, param2)?;
// 3. Send to next node
ctx.send_next(new_msg.clone()).await?;
Ok(new_msg)
}
fn get_descriptor(&self) -> NodeDescriptor {
NodeDescriptor {
type_name: "custom/type".to_string(),
name: "Custom Node".to_string(),
description: "This is a custom processing node".to_string(),
node_type: NodeType::Middle,
}
}
}
engine.register_node_type("custom/type", Arc::new(|config| {
Ok(Arc::new(CustomNode::new(config)) as Arc<dyn NodeHandler>)
})).await;
The project includes multiple complete examples:
Rule Chain Design
Component Development
Performance Optimization
For more detailed documentation, please refer to:
Thanks to the following projects and libraries for inspiring and helping rule-rs:
MIT License