dataflow_rs/engine/
workflow.rs1use crate::engine::error::{DataflowError, Result};
2use crate::engine::task::Task;
3use serde::Deserialize;
4use serde_json::Value;
5use std::fs;
6use std::path::Path;
7
8#[derive(Deserialize, Clone, Debug)]
9pub struct Workflow {
10 pub id: String,
11 pub name: String,
12 pub priority: u32,
13 pub description: Option<String>,
14 pub condition: Option<Value>,
15 pub tasks: Vec<Task>,
16}
17
18impl Default for Workflow {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23
24impl Workflow {
25 pub fn new() -> Self {
26 Workflow {
27 id: String::new(),
28 name: String::new(),
29 priority: 0,
30 description: None,
31 condition: None,
32 tasks: Vec::new(),
33 }
34 }
35
36 pub fn from_json(json_str: &str) -> Result<Self> {
38 serde_json::from_str(json_str).map_err(DataflowError::from_serde)
39 }
40
41 pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
43 let json_str = fs::read_to_string(path).map_err(DataflowError::from_io)?;
44
45 Self::from_json(&json_str)
46 }
47
48 pub fn validate(&self) -> Result<()> {
50 if self.id.is_empty() {
52 return Err(DataflowError::Workflow(
53 "Workflow id cannot be empty".to_string(),
54 ));
55 }
56
57 if self.name.is_empty() {
58 return Err(DataflowError::Workflow(
59 "Workflow name cannot be empty".to_string(),
60 ));
61 }
62
63 if self.tasks.is_empty() {
65 return Err(DataflowError::Workflow(
66 "Workflow must have at least one task".to_string(),
67 ));
68 }
69
70 let mut task_ids = std::collections::HashSet::new();
72 for task in &self.tasks {
73 if !task_ids.insert(&task.id) {
74 return Err(DataflowError::Workflow(format!(
75 "Duplicate task ID '{}' in workflow",
76 task.id
77 )));
78 }
79 }
80
81 Ok(())
82 }
83}