Skip to main content

cloacina_workflow/
error.rs

1/*
2 *  Copyright 2025-2026 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    /// Database operation failed (infrastructure error, not a key issue)
55    #[error("Database error: {0}")]
56    Database(String),
57
58    /// Connection pool exhausted or unavailable
59    #[error("Connection pool error: {0}")]
60    ConnectionPool(String),
61}
62
63/// Errors that can occur during task execution.
64///
65/// Task errors encompass execution failures, context issues, and
66/// any other problems that prevent a task from completing successfully.
67#[derive(Debug, Error)]
68pub enum TaskError {
69    /// Task execution failed with a message
70    #[error("Task execution failed: {message}")]
71    ExecutionFailed {
72        message: String,
73        task_id: String,
74        timestamp: DateTime<Utc>,
75    },
76
77    /// Task dependency not satisfied
78    #[error("Task dependency not satisfied: {dependency} required by {task_id}")]
79    DependencyNotSatisfied { dependency: String, task_id: String },
80
81    /// Task exceeded timeout
82    #[error("Task timeout: {task_id} exceeded {timeout_seconds}s")]
83    Timeout {
84        task_id: String,
85        timeout_seconds: u64,
86    },
87
88    /// Context operation error within a task
89    #[error("Context error in task {task_id}: {error}")]
90    ContextError {
91        task_id: String,
92        error: ContextError,
93    },
94
95    /// Task validation failed
96    #[error("Task validation failed: {message}")]
97    ValidationFailed { message: String },
98
99    /// Unknown error
100    #[error("Unknown error in task {task_id}: {message}")]
101    Unknown { task_id: String, message: String },
102
103    /// Task readiness check failed
104    #[error("Task readiness check failed: {task_id}")]
105    ReadinessCheckFailed { task_id: String },
106
107    /// Trigger rule evaluation failed
108    #[error("Trigger rule evaluation failed: {task_id}")]
109    TriggerRuleFailed { task_id: String },
110}
111
112impl From<ContextError> for TaskError {
113    fn from(error: ContextError) -> Self {
114        TaskError::ContextError {
115            task_id: "unknown".to_string(),
116            error,
117        }
118    }
119}
120
121/// Errors that can occur during task checkpointing.
122///
123/// Checkpoint errors occur when tasks attempt to save intermediate state
124/// for recovery purposes.
125#[derive(Debug, Error)]
126pub enum CheckpointError {
127    /// Failed to save checkpoint
128    #[error("Failed to save checkpoint for task {task_id}: {message}")]
129    SaveFailed { task_id: String, message: String },
130
131    /// Failed to load checkpoint
132    #[error("Failed to load checkpoint for task {task_id}: {message}")]
133    LoadFailed { task_id: String, message: String },
134
135    /// Checkpoint serialization error
136    #[error("Checkpoint serialization error: {0}")]
137    Serialization(#[from] serde_json::Error),
138
139    /// Checkpoint storage error
140    #[error("Checkpoint storage error: {message}")]
141    StorageError { message: String },
142
143    /// Checkpoint validation failed
144    #[error("Checkpoint validation failed: {message}")]
145    ValidationFailed { message: String },
146}