Skip to main content

sh_layer2/workflow_engine/
mod.rs

1//! # Workflow Engine
2//!
3//! DAG 工作流引擎,支持节点依赖和并行执行。
4
5mod dag;
6mod executor;
7mod node;
8
9pub use dag::Dag;
10pub use executor::WorkflowExecutor;
11pub use node::{Node, NodeStatus};
12
13use async_trait::async_trait;
14use serde::{Deserialize, Serialize};
15
16use crate::types::{Layer2Result, TaskId};
17
18/// 工作流输入
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct WorkflowInput {
21    pub task: String,
22    pub context: serde_json::Value,
23}
24
25/// 工作流输出
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct WorkflowOutput {
28    pub task_id: TaskId,
29    pub results: Vec<NodeResult>,
30    pub status: WorkflowStatus,
31    pub duration_ms: u64,
32}
33
34/// 节点执行结果
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct NodeResult {
37    pub node_id: String,
38    pub status: NodeStatus,
39    pub output: Option<serde_json::Value>,
40    pub error: Option<String>,
41    pub duration_ms: u64,
42}
43
44/// 工作流状态
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
46pub enum WorkflowStatus {
47    Pending,
48    Running,
49    Completed,
50    Failed,
51    Cancelled,
52}
53
54/// 工作流引擎接口
55#[async_trait]
56pub trait WorkflowEngineTrait: Send + Sync {
57    /// 添加节点
58    fn add_node(&mut self, node: Node) -> Layer2Result<()>;
59
60    /// 添加边(依赖关系)
61    fn add_edge(&mut self, from: &str, to: &str) -> Layer2Result<()>;
62
63    /// 执行工作流
64    async fn execute(&self, input: WorkflowInput) -> Layer2Result<WorkflowOutput>;
65
66    /// 取消工作流
67    async fn cancel(&self, task_id: &TaskId) -> Layer2Result<bool>;
68
69    /// 获取工作流状态
70    fn status(&self, task_id: &TaskId) -> Layer2Result<WorkflowStatus>;
71
72    /// 验证 DAG 结构
73    fn validate(&self) -> Layer2Result<Vec<String>>;
74
75    /// 获取节点数量
76    fn node_count(&self) -> usize;
77
78    /// 获取边数量
79    fn edge_count(&self) -> usize;
80}
81
82/// 节点执行器接口
83#[async_trait]
84pub trait NodeExecutor: Send + Sync {
85    /// 执行节点
86    async fn execute(&self, node: &Node, input: &WorkflowInput) -> Layer2Result<serde_json::Value>;
87}
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92
93    #[test]
94    fn test_workflow_input_creation() {
95        let input = WorkflowInput {
96            task: "test".to_string(),
97            context: serde_json::Value::Null,
98        };
99        assert_eq!(input.task, "test");
100    }
101}