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

@ -12,6 +12,8 @@ pub struct FlowEngine {
impl FlowEngine {
pub fn new(tasks: TaskRegistry) -> Self { Self { tasks } }
pub fn builder() -> FlowEngineBuilder { FlowEngineBuilder::default() }
pub async fn drive(&self, chain: &ChainDef, mut ctx: serde_json::Value, opts: DriveOptions) -> anyhow::Result<(serde_json::Value, Vec<String>)> {
let mut logs = Vec::new();
@ -58,19 +60,20 @@ impl FlowEngine {
if let Some(task) = self.tasks.get(task_name) {
match opts.execution_mode {
ExecutionMode::Sync => {
if let serde_json::Value::Object(obj) = &mut ctx { obj.insert("__current_node_id".to_string(), serde_json::Value::String(node.id.0.clone())); }
task.execute(&mut ctx).await?;
// 直接传入 node_id 与 node避免对 ctx 魔法字段的依赖
task.execute(&node.id, node, &mut ctx).await?;
logs.push(format!("exec task: {} (sync)", task_name));
info!(target: "udmin.flow", "exec task: {} (sync)", task_name);
}
ExecutionMode::AsyncFireAndForget => {
// fire-and-forget: 复制一份上下文供该任务使用,主流程不等待
let mut task_ctx = ctx.clone();
if let serde_json::Value::Object(obj) = &mut task_ctx { obj.insert("__current_node_id".to_string(), serde_json::Value::String(node.id.0.clone())); }
let task_arc = task.clone();
let name_for_log = task_name.clone();
let node_id = node.id.clone();
let node_def = (*node).clone();
tokio::spawn(async move {
let _ = task_arc.execute(&mut task_ctx).await;
let _ = task_arc.execute(&node_id, &node_def, &mut task_ctx).await;
info!(target: "udmin.flow", "exec task done (async): {}", name_for_log);
});
logs.push(format!("spawn task: {} (async)", task_name));
@ -122,6 +125,23 @@ impl FlowEngine {
}
}
#[derive(Default)]
pub struct FlowEngineBuilder {
tasks: Option<TaskRegistry>,
}
impl FlowEngineBuilder {
pub fn tasks(mut self, reg: TaskRegistry) -> Self { self.tasks = Some(reg); self }
pub fn build(self) -> FlowEngine {
let tasks = self.tasks.unwrap_or_else(|| crate::flow::task::default_registry());
FlowEngine { tasks }
}
}
impl Default for FlowEngine {
fn default() -> Self { Self { tasks: crate::flow::task::default_registry() } }
}
fn eval_condition_json(ctx: &serde_json::Value, cond: &serde_json::Value) -> anyhow::Result<bool> {
// 目前支持前端 Condition 组件导出的: { left:{type, content}, operator, right? }
let left = cond.get("left").ok_or_else(|| anyhow::anyhow!("missing left"))?;