Skip to main content

oximedia_batch/
error.rs

1//! Error types for batch processing
2
3use thiserror::Error;
4
5/// Result type for batch operations
6pub type Result<T> = std::result::Result<T, BatchError>;
7
8/// Batch processing errors
9#[derive(Error, Debug)]
10pub enum BatchError {
11    /// Job not found
12    #[error("Job not found: {0}")]
13    JobNotFound(String),
14
15    /// Invalid job configuration
16    #[error("Invalid job configuration: {0}")]
17    InvalidJobConfig(String),
18
19    /// Database error
20    #[error("Database error: {0}")]
21    #[cfg(all(not(target_arch = "wasm32"), feature = "sqlite"))]
22    DatabaseError(#[from] rusqlite::Error),
23
24    /// Database error (non-sqlite or wasm32 variant)
25    #[error("Database error: {0}")]
26    #[cfg(any(target_arch = "wasm32", not(feature = "sqlite")))]
27    DatabaseError(String),
28
29    /// I/O error
30    #[error("I/O error: {0}")]
31    IoError(#[from] std::io::Error),
32
33    /// Serialization error
34    #[error("Serialization error: {0}")]
35    SerializationError(#[from] serde_json::Error),
36
37    /// Template error
38    #[error("Template error: {0}")]
39    TemplateError(String),
40
41    /// Execution error
42    #[error("Execution error: {0}")]
43    ExecutionError(String),
44
45    /// Worker error
46    #[error("Worker error: {0}")]
47    WorkerError(String),
48
49    /// Queue error
50    #[error("Queue error: {0}")]
51    QueueError(String),
52
53    /// Script error
54    #[error("Script error: {0}")]
55    ScriptError(String),
56
57    /// Watch folder error
58    #[error("Watch folder error: {0}")]
59    WatchError(String),
60
61    /// API error
62    #[error("API error: {0}")]
63    ApiError(String),
64
65    /// Validation error
66    #[error("Validation error: {0}")]
67    ValidationError(String),
68
69    /// Dependency error
70    #[error("Job dependency error: {0}")]
71    DependencyError(String),
72
73    /// Resource allocation error
74    #[error("Resource allocation error: {0}")]
75    ResourceError(String),
76
77    /// Retry exhausted
78    #[error("Retry attempts exhausted for job: {0}")]
79    RetryExhausted(String),
80
81    /// Cancelled
82    #[error("Job cancelled: {0}")]
83    Cancelled(String),
84
85    /// Timeout
86    #[error("Operation timeout: {0}")]
87    Timeout(String),
88
89    /// Pattern matching error
90    #[error("Pattern matching error: {0}")]
91    PatternError(String),
92
93    /// File operation error
94    #[error("File operation error: {0}")]
95    FileOperationError(String),
96
97    /// Media operation error
98    #[error("Media operation error: {0}")]
99    MediaOperationError(String),
100
101    /// Integration error
102    #[error("Integration error: {0}")]
103    IntegrationError(String),
104}
105
106#[cfg(all(not(target_arch = "wasm32"), feature = "scripting"))]
107impl From<mlua::Error> for BatchError {
108    fn from(err: mlua::Error) -> Self {
109        Self::ScriptError(err.to_string())
110    }
111}
112
113#[cfg(not(target_arch = "wasm32"))]
114impl From<notify::Error> for BatchError {
115    fn from(err: notify::Error) -> Self {
116        Self::WatchError(err.to_string())
117    }
118}
119
120impl From<regex::Error> for BatchError {
121    fn from(err: regex::Error) -> Self {
122        Self::PatternError(err.to_string())
123    }
124}
125
126impl From<glob::PatternError> for BatchError {
127    fn from(err: glob::PatternError) -> Self {
128        Self::PatternError(err.to_string())
129    }
130}
131
132#[cfg(all(not(target_arch = "wasm32"), feature = "sqlite"))]
133impl From<r2d2::Error> for BatchError {
134    fn from(err: r2d2::Error) -> Self {
135        Self::FileOperationError(format!("Connection pool error: {err}"))
136    }
137}
138
139impl From<walkdir::Error> for BatchError {
140    fn from(err: walkdir::Error) -> Self {
141        Self::FileOperationError(err.to_string())
142    }
143}
144
145#[cfg(test)]
146mod tests {
147    use super::*;
148
149    #[test]
150    fn test_error_display() {
151        let err = BatchError::JobNotFound("test-job".to_string());
152        assert_eq!(err.to_string(), "Job not found: test-job");
153    }
154
155    #[test]
156    fn test_invalid_config_error() {
157        let err = BatchError::InvalidJobConfig("missing field".to_string());
158        assert!(err.to_string().contains("Invalid job configuration"));
159    }
160
161    #[test]
162    fn test_template_error() {
163        let err = BatchError::TemplateError("invalid syntax".to_string());
164        assert!(err.to_string().contains("Template error"));
165    }
166
167    #[test]
168    fn test_execution_error() {
169        let err = BatchError::ExecutionError("worker failed".to_string());
170        assert!(err.to_string().contains("Execution error"));
171    }
172
173    #[test]
174    fn test_retry_exhausted() {
175        let err = BatchError::RetryExhausted("job-123".to_string());
176        assert!(err.to_string().contains("Retry attempts exhausted"));
177    }
178
179    #[test]
180    fn test_cancelled() {
181        let err = BatchError::Cancelled("job-456".to_string());
182        assert!(err.to_string().contains("Job cancelled"));
183    }
184
185    #[test]
186    fn test_timeout() {
187        let err = BatchError::Timeout("operation took too long".to_string());
188        assert!(err.to_string().contains("Operation timeout"));
189    }
190}