feat(flow): 重构流程引擎与任务执行器架构

重构流程引擎核心组件,引入执行器接口Executor替代原有TaskComponent,优化节点配置映射逻辑:
1. 新增mappers模块集中处理节点配置提取
2. 为存储层添加Storage trait抽象
3. 移除对ctx魔法字段的依赖,直接传递节点信息
4. 增加构建器模式支持引擎创建
5. 完善DSL解析的输入校验

同时标记部分未使用代码为allow(dead_code)
This commit is contained in:
2025-09-16 23:58:28 +08:00
parent 65764a2cbc
commit 81757eecf5
13 changed files with 375 additions and 164 deletions

View File

@ -0,0 +1,35 @@
use serde_json::Value;
// Extract db config: sql, params, outputKey, connection from a node
pub fn extract_db_cfg(n: &Value) -> Option<Value> {
let data = n.get("data");
let db_cfg = data.and_then(|d| d.get("db")).and_then(|v| v.as_object())?;
let mut db_obj = serde_json::Map::new();
// sql can be string or object with content
let raw_sql = db_cfg.get("sql");
let sql = match raw_sql {
Some(Value::String(s)) => super::sanitize_wrapped(s),
Some(Value::Object(o)) => o
.get("content")
.and_then(|v| v.as_str())
.map(super::sanitize_wrapped)
.unwrap_or_default(),
_ => String::new(),
};
if !sql.is_empty() {
db_obj.insert("sql".into(), Value::String(sql));
}
if let Some(p) = db_cfg.get("params") {
db_obj.insert("params".into(), p.clone());
}
if let Some(Value::String(k)) = db_cfg.get("outputKey") {
db_obj.insert("outputKey".into(), Value::String(k.clone()));
}
if let Some(conn) = db_cfg.get("connection") {
db_obj.insert("connection".into(), conn.clone());
}
if db_obj.is_empty() { None } else { Some(Value::Object(db_obj)) }
}

View File

@ -0,0 +1,65 @@
use serde_json::Value;
// Extract http config: method, url, headers, query, body from a node
pub fn extract_http_cfg(n: &Value) -> Option<Value> {
let data = n.get("data");
let api = data.and_then(|d| d.get("api"));
let method = api
.and_then(|a| a.get("method"))
.and_then(|v| v.as_str())
.unwrap_or("GET")
.to_string();
let url_val = api.and_then(|a| a.get("url"));
let raw_url = match url_val {
Some(Value::String(s)) => s.clone(),
Some(Value::Object(obj)) => obj
.get("content")
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string(),
_ => String::new(),
};
let url = super::sanitize_wrapped(&raw_url);
if url.is_empty() {
return None;
}
let mut http_obj = serde_json::Map::new();
http_obj.insert("method".into(), Value::String(method));
http_obj.insert("url".into(), Value::String(url));
// Optional: headers
if let Some(hs) = api.and_then(|a| a.get("headers")).and_then(|v| v.as_object()) {
let mut heads = serde_json::Map::new();
for (k, v) in hs.iter() {
if let Some(s) = v.as_str() {
heads.insert(k.clone(), Value::String(s.to_string()));
}
}
if !heads.is_empty() {
http_obj.insert("headers".into(), Value::Object(heads));
}
}
// Optional: query
if let Some(qs) = api.and_then(|a| a.get("query")).and_then(|v| v.as_object()) {
let mut query = serde_json::Map::new();
for (k, v) in qs.iter() {
query.insert(k.clone(), v.clone());
}
if !query.is_empty() {
http_obj.insert("query".into(), Value::Object(query));
}
}
// Optional: body
if let Some(body_obj) = data.and_then(|d| d.get("body")).and_then(|v| v.as_object()) {
if let Some(Value::Object(json_body)) = body_obj.get("json") {
http_obj.insert("body".into(), Value::Object(json_body.clone()));
} else if let Some(Value::String(s)) = body_obj.get("content") {
http_obj.insert("body".into(), Value::String(s.clone()));
}
}
Some(Value::Object(http_obj))
}