1use anyhow::Result;
6use std::collections::HashMap;
7
8#[derive(Debug, Clone)]
10pub struct ExecutionPlan {
11 pub phases: Vec<ExecutionPhase>,
13 pub env_vars: HashMap<String, serde_yaml::Value>,
15 pub flow_vars: HashMap<String, serde_yaml::Value>,
17 pub metadata: PlanMetadata,
19}
20
21#[derive(Debug, Clone)]
23pub struct ExecutionPhase {
24 pub id: String,
26 pub name: String,
28 pub execution_mode: PhaseExecutionMode,
30 pub nodes: Vec<ExecutionNode>,
32 pub condition: Option<String>,
34}
35
36#[derive(Debug, Clone)]
38pub enum PhaseExecutionMode {
39 Sequential,
41 Parallel,
43 Conditional { condition: String },
45}
46
47#[derive(Debug, Clone)]
49pub struct ExecutionNode {
50 pub id: String,
52 pub name: String,
54 pub node_type: NodeType,
56 pub action_spec: ActionSpec,
58 pub dependencies: Vec<String>,
60 pub condition: Option<String>,
62 pub priority: u32,
64 pub retry_config: Option<RetryConfig>,
66 pub timeout_config: Option<TimeoutConfig>,
68}
69
70#[derive(Debug, Clone)]
72pub enum NodeType {
73 Action,
75 Condition,
77 Branch,
79 Loop,
81 Subprocess,
83}
84
85#[derive(Debug, Clone)]
87pub struct ActionSpec {
88 pub action_type: String,
90 pub parameters: HashMap<String, serde_yaml::Value>,
92 pub outputs: HashMap<String, serde_yaml::Value>,
94}
95
96#[derive(Debug, Clone)]
98pub struct RetryConfig {
99 pub max_retries: u32,
101 pub delay: u64,
103 pub strategy: RetryStrategy,
105}
106
107#[derive(Debug, Clone)]
109pub enum RetryStrategy {
110 Fixed,
112 Exponential { multiplier: f64 },
114 Linear { increment: u64 },
116}
117
118#[derive(Debug, Clone)]
120pub struct TimeoutConfig {
121 pub duration: u64,
123 pub on_timeout: Option<String>,
125}
126
127#[derive(Debug, Clone)]
129pub struct PlanMetadata {
130 pub plan_id: String,
132 pub created_at: std::time::SystemTime,
134 pub workflow_name: String,
136 pub workflow_version: String,
138 pub total_nodes: usize,
140 pub total_phases: usize,
142}
143
144pub trait Executor {
146 type Input;
147 type Output;
148 type Error;
149
150 fn execute(
152 &mut self,
153 input: Self::Input,
154 ) -> impl std::future::Future<Output = Result<Self::Output, Self::Error>> + Send;
155
156 fn status(&self) -> ExecutorStatus;
158
159 fn stop(
161 &mut self,
162 ) -> impl std::future::Future<Output = Result<(), Self::Error>> + Send;
163}
164
165#[derive(Debug, Clone, PartialEq)]
167pub enum ExecutorStatus {
168 Idle,
170 Running,
172 Stopped,
174 Error(String),
176}
177
178pub trait ConfigParser<T> {
180 type Output;
181 type Error;
182
183 fn parse(&self, config: T) -> Result<Self::Output, Self::Error>;
185}
186
187pub trait FlowPlanner {
189 type Input;
190 type Output;
191 type Error;
192
193 fn create_execution_plan(
195 &self,
196 input: Self::Input,
197 ) -> Result<Self::Output, Self::Error>;
198
199 fn optimize_plan(
201 &self,
202 plan: Self::Output,
203 ) -> Result<Self::Output, Self::Error>;
204}
205
206pub trait ExpressionEvaluator {
208 type Value;
209 type Error;
210
211 fn evaluate(&self, expression: &str) -> Result<Self::Value, Self::Error>;
213
214 fn evaluate_condition(&self, condition: &str) -> Result<bool, Self::Error>;
216
217 fn set_variable(&mut self, name: String, value: Self::Value);
219
220 fn get_variable(&self, name: &str) -> Option<Self::Value>;
222}
223
224impl ExecutionPlan {
225 pub fn new(
227 workflow_name: String,
228 workflow_version: String,
229 env_vars: HashMap<String, serde_yaml::Value>,
230 flow_vars: HashMap<String, serde_yaml::Value>,
231 ) -> Self {
232 let metadata = PlanMetadata {
233 plan_id: uuid::Uuid::new_v4().to_string(),
234 created_at: std::time::SystemTime::now(),
235 workflow_name,
236 workflow_version,
237 total_nodes: 0,
238 total_phases: 0,
239 };
240
241 Self {
242 phases: Vec::new(),
243 env_vars,
244 flow_vars,
245 metadata,
246 }
247 }
248
249 pub fn add_phase(&mut self, phase: ExecutionPhase) {
251 self.metadata.total_nodes += phase.nodes.len();
252 self.phases.push(phase);
253 self.metadata.total_phases = self.phases.len();
254 }
255
256 pub fn estimated_duration(&self) -> std::time::Duration {
258 let total_nodes = self.metadata.total_nodes;
260 std::time::Duration::from_millis((total_nodes * 100) as u64)
261 }
262
263 pub fn validate(&self) -> Result<(), String> {
265 if self.phases.is_empty() {
266 return Err("执行计划不能为空".to_string());
267 }
268
269 for phase in &self.phases {
271 if phase.nodes.is_empty() {
272 return Err(format!("阶段 {} 不能为空", phase.name));
273 }
274 }
275
276 Ok(())
277 }
278}
279
280impl ExecutionNode {
281 pub fn new(id: String, name: String, action_spec: ActionSpec) -> Self {
283 Self {
284 id,
285 name,
286 node_type: NodeType::Action,
287 action_spec,
288 dependencies: Vec::new(),
289 condition: None,
290 priority: 100,
291 retry_config: None,
292 timeout_config: None,
293 }
294 }
295
296 pub fn add_dependency(mut self, dependency: String) -> Self {
298 self.dependencies.push(dependency);
299 self
300 }
301
302 pub fn with_condition(mut self, condition: String) -> Self {
304 self.condition = Some(condition);
305 self
306 }
307
308 pub fn with_priority(mut self, priority: u32) -> Self {
310 self.priority = priority;
311 self
312 }
313
314 pub fn with_retry(mut self, retry_config: RetryConfig) -> Self {
316 self.retry_config = Some(retry_config);
317 self
318 }
319
320 pub fn with_timeout(mut self, timeout_config: TimeoutConfig) -> Self {
322 self.timeout_config = Some(timeout_config);
323 self
324 }
325}