cloacina_workflow/error.rs
1/*
2 * Copyright 2025 Colliery Software
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//! # Error Types
18//!
19//! This module defines the minimal error types needed for workflow authoring.
20//! These errors do not include database or runtime-specific variants, which
21//! are defined in the main `cloacina` crate.
22//!
23//! ## Error Types
24//!
25//! - [`ContextError`]: Errors related to context operations
26//! - [`TaskError`]: Errors that occur during task execution
27//! - [`CheckpointError`]: Errors in task checkpointing
28
29use chrono::{DateTime, Utc};
30use thiserror::Error;
31
32/// Errors that can occur during context operations.
33///
34/// This minimal version only includes errors that can occur without database
35/// or runtime dependencies.
36#[derive(Debug, Error)]
37pub enum ContextError {
38 /// JSON serialization/deserialization error
39 #[error("Serialization error: {0}")]
40 Serialization(#[from] serde_json::Error),
41
42 /// Key not found in context
43 #[error("Key not found: {0}")]
44 KeyNotFound(String),
45
46 /// Type mismatch when retrieving a value
47 #[error("Type mismatch for key {0}")]
48 TypeMismatch(String),
49
50 /// Key already exists when inserting
51 #[error("Key already exists: {0}")]
52 KeyExists(String),
53}
54
55/// Errors that can occur during task execution.
56///
57/// Task errors encompass execution failures, context issues, and
58/// any other problems that prevent a task from completing successfully.
59#[derive(Debug, Error)]
60pub enum TaskError {
61 /// Task execution failed with a message
62 #[error("Task execution failed: {message}")]
63 ExecutionFailed {
64 message: String,
65 task_id: String,
66 timestamp: DateTime<Utc>,
67 },
68
69 /// Task dependency not satisfied
70 #[error("Task dependency not satisfied: {dependency} required by {task_id}")]
71 DependencyNotSatisfied { dependency: String, task_id: String },
72
73 /// Task exceeded timeout
74 #[error("Task timeout: {task_id} exceeded {timeout_seconds}s")]
75 Timeout {
76 task_id: String,
77 timeout_seconds: u64,
78 },
79
80 /// Context operation error within a task
81 #[error("Context error in task {task_id}: {error}")]
82 ContextError {
83 task_id: String,
84 error: ContextError,
85 },
86
87 /// Task validation failed
88 #[error("Task validation failed: {message}")]
89 ValidationFailed { message: String },
90
91 /// Unknown error
92 #[error("Unknown error in task {task_id}: {message}")]
93 Unknown { task_id: String, message: String },
94
95 /// Task readiness check failed
96 #[error("Task readiness check failed: {task_id}")]
97 ReadinessCheckFailed { task_id: String },
98
99 /// Trigger rule evaluation failed
100 #[error("Trigger rule evaluation failed: {task_id}")]
101 TriggerRuleFailed { task_id: String },
102}
103
104impl From<ContextError> for TaskError {
105 fn from(error: ContextError) -> Self {
106 TaskError::ContextError {
107 task_id: "unknown".to_string(),
108 error,
109 }
110 }
111}
112
113/// Errors that can occur during task checkpointing.
114///
115/// Checkpoint errors occur when tasks attempt to save intermediate state
116/// for recovery purposes.
117#[derive(Debug, Error)]
118pub enum CheckpointError {
119 /// Failed to save checkpoint
120 #[error("Failed to save checkpoint for task {task_id}: {message}")]
121 SaveFailed { task_id: String, message: String },
122
123 /// Failed to load checkpoint
124 #[error("Failed to load checkpoint for task {task_id}: {message}")]
125 LoadFailed { task_id: String, message: String },
126
127 /// Checkpoint serialization error
128 #[error("Checkpoint serialization error: {0}")]
129 Serialization(#[from] serde_json::Error),
130
131 /// Checkpoint storage error
132 #[error("Checkpoint storage error: {message}")]
133 StorageError { message: String },
134
135 /// Checkpoint validation failed
136 #[error("Checkpoint validation failed: {message}")]
137 ValidationFailed { message: String },
138}