mod dag;
mod executor;
mod node;
pub use dag::Dag;
pub use executor::WorkflowExecutor;
pub use node::{Node, NodeStatus};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use crate::types::{Layer2Result, TaskId};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkflowInput {
pub task: String,
pub context: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkflowOutput {
pub task_id: TaskId,
pub results: Vec<NodeResult>,
pub status: WorkflowStatus,
pub duration_ms: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NodeResult {
pub node_id: String,
pub status: NodeStatus,
pub output: Option<serde_json::Value>,
pub error: Option<String>,
pub duration_ms: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum WorkflowStatus {
Pending,
Running,
Completed,
Failed,
Cancelled,
}
#[async_trait]
pub trait WorkflowEngineTrait: Send + Sync {
fn add_node(&mut self, node: Node) -> Layer2Result<()>;
fn add_edge(&mut self, from: &str, to: &str) -> Layer2Result<()>;
async fn execute(&self, input: WorkflowInput) -> Layer2Result<WorkflowOutput>;
async fn cancel(&self, task_id: &TaskId) -> Layer2Result<bool>;
fn status(&self, task_id: &TaskId) -> Layer2Result<WorkflowStatus>;
fn validate(&self) -> Layer2Result<Vec<String>>;
fn node_count(&self) -> usize;
fn edge_count(&self) -> usize;
}
#[async_trait]
pub trait NodeExecutor: Send + Sync {
async fn execute(&self, node: &Node, input: &WorkflowInput) -> Layer2Result<serde_json::Value>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_workflow_input_creation() {
let input = WorkflowInput {
task: "test".to_string(),
context: serde_json::Value::Null,
};
assert_eq!(input.task, "test");
}
}