oxigdal_workflow/
error.rs1pub type Result<T> = std::result::Result<T, WorkflowError>;
5
6#[derive(Debug, thiserror::Error)]
8pub enum WorkflowError {
9 #[error("Workflow execution error: {0}")]
11 Execution(String),
12
13 #[error("Workflow validation error: {0}")]
15 Validation(String),
16
17 #[error("Workflow scheduling error: {0}")]
19 Scheduling(String),
20
21 #[error("DAG error: {0}")]
23 Dag(#[from] DagError),
24
25 #[error("Task execution error in '{task_id}': {message}")]
27 TaskExecution {
28 task_id: String,
30 message: String,
32 },
33
34 #[error("Task '{task_id}' timed out after {timeout_secs}s")]
36 TaskTimeout {
37 task_id: String,
39 timeout_secs: u64,
41 },
42
43 #[error("Workflow state error: {0}")]
45 State(String),
46
47 #[error("Workflow not found: {0}")]
49 NotFound(String),
50
51 #[error("Workflow already exists: {0}")]
53 AlreadyExists(String),
54
55 #[error("Conditional expression error: {0}")]
57 ConditionalExpression(String),
58
59 #[error("Template error: {0}")]
61 Template(String),
62
63 #[error("Versioning error: {0}")]
65 Versioning(String),
66
67 #[error("Integration error with {service}: {message}")]
69 Integration {
70 service: String,
72 message: String,
74 },
75
76 #[error("Serialization error: {0}")]
78 Serialization(#[from] serde_json::Error),
79
80 #[error("I/O error: {0}")]
82 Io(#[from] std::io::Error),
83
84 #[error("Invalid cron expression: {0}")]
86 CronExpression(String),
87
88 #[error("Persistence error: {0}")]
90 Persistence(String),
91
92 #[error("Monitoring error: {0}")]
94 Monitoring(String),
95
96 #[error("Resource exhausted: {0}")]
98 ResourceExhausted(String),
99
100 #[error("Deadlock detected in workflow '{workflow_id}'")]
102 Deadlock {
103 workflow_id: String,
105 },
106
107 #[error("Invalid parameter '{param}': {message}")]
109 InvalidParameter {
110 param: String,
112 message: String,
114 },
115
116 #[error("Internal error: {0}")]
118 Internal(String),
119}
120
121#[derive(Debug, thiserror::Error)]
123pub enum DagError {
124 #[error("Cycle detected in DAG: {0}")]
126 CycleDetected(String),
127
128 #[error("Invalid node ID: {0}")]
130 InvalidNode(String),
131
132 #[error("Invalid edge from '{from}' to '{to}': {message}")]
134 InvalidEdge {
135 from: String,
137 to: String,
139 message: String,
141 },
142
143 #[error("DAG is empty")]
145 EmptyDag,
146
147 #[error("Unreachable node: {0}")]
149 UnreachableNode(String),
150
151 #[error("Missing dependency: {0}")]
153 MissingDependency(String),
154}
155
156impl WorkflowError {
157 pub fn execution<S: Into<String>>(msg: S) -> Self {
159 Self::Execution(msg.into())
160 }
161
162 pub fn validation<S: Into<String>>(msg: S) -> Self {
164 Self::Validation(msg.into())
165 }
166
167 pub fn scheduling<S: Into<String>>(msg: S) -> Self {
169 Self::Scheduling(msg.into())
170 }
171
172 pub fn state<S: Into<String>>(msg: S) -> Self {
174 Self::State(msg.into())
175 }
176
177 pub fn not_found<S: Into<String>>(id: S) -> Self {
179 Self::NotFound(id.into())
180 }
181
182 pub fn already_exists<S: Into<String>>(id: S) -> Self {
184 Self::AlreadyExists(id.into())
185 }
186
187 pub fn task_execution<S1: Into<String>, S2: Into<String>>(task_id: S1, message: S2) -> Self {
189 Self::TaskExecution {
190 task_id: task_id.into(),
191 message: message.into(),
192 }
193 }
194
195 pub fn task_timeout<S: Into<String>>(task_id: S, timeout_secs: u64) -> Self {
197 Self::TaskTimeout {
198 task_id: task_id.into(),
199 timeout_secs,
200 }
201 }
202
203 pub fn conditional<S: Into<String>>(msg: S) -> Self {
205 Self::ConditionalExpression(msg.into())
206 }
207
208 pub fn template<S: Into<String>>(msg: S) -> Self {
210 Self::Template(msg.into())
211 }
212
213 pub fn versioning<S: Into<String>>(msg: S) -> Self {
215 Self::Versioning(msg.into())
216 }
217
218 pub fn integration<S1: Into<String>, S2: Into<String>>(service: S1, message: S2) -> Self {
220 Self::Integration {
221 service: service.into(),
222 message: message.into(),
223 }
224 }
225
226 pub fn cron_expression<S: Into<String>>(msg: S) -> Self {
228 Self::CronExpression(msg.into())
229 }
230
231 pub fn persistence<S: Into<String>>(msg: S) -> Self {
233 Self::Persistence(msg.into())
234 }
235
236 pub fn monitoring<S: Into<String>>(msg: S) -> Self {
238 Self::Monitoring(msg.into())
239 }
240
241 pub fn resource_exhausted<S: Into<String>>(msg: S) -> Self {
243 Self::ResourceExhausted(msg.into())
244 }
245
246 pub fn deadlock<S: Into<String>>(workflow_id: S) -> Self {
248 Self::Deadlock {
249 workflow_id: workflow_id.into(),
250 }
251 }
252
253 pub fn invalid_parameter<S1: Into<String>, S2: Into<String>>(param: S1, message: S2) -> Self {
255 Self::InvalidParameter {
256 param: param.into(),
257 message: message.into(),
258 }
259 }
260
261 pub fn internal<S: Into<String>>(msg: S) -> Self {
263 Self::Internal(msg.into())
264 }
265}
266
267impl DagError {
268 pub fn cycle<S: Into<String>>(path: S) -> Self {
270 Self::CycleDetected(path.into())
271 }
272
273 pub fn invalid_node<S: Into<String>>(node_id: S) -> Self {
275 Self::InvalidNode(node_id.into())
276 }
277
278 pub fn invalid_edge<S1: Into<String>, S2: Into<String>, S3: Into<String>>(
280 from: S1,
281 to: S2,
282 message: S3,
283 ) -> Self {
284 Self::InvalidEdge {
285 from: from.into(),
286 to: to.into(),
287 message: message.into(),
288 }
289 }
290
291 pub fn missing_dependency<S: Into<String>>(dep: S) -> Self {
293 Self::MissingDependency(dep.into())
294 }
295}