use thiserror::Error;
pub type Result<T> = std::result::Result<T, BatchError>;
#[derive(Error, Debug)]
pub enum BatchError {
#[error("Job not found: {0}")]
JobNotFound(String),
#[error("Invalid job configuration: {0}")]
InvalidJobConfig(String),
#[error("Database error: {0}")]
#[cfg(all(not(target_arch = "wasm32"), feature = "sqlite"))]
DatabaseError(#[from] rusqlite::Error),
#[error("Database error: {0}")]
#[cfg(any(target_arch = "wasm32", not(feature = "sqlite")))]
DatabaseError(String),
#[error("I/O error: {0}")]
IoError(#[from] std::io::Error),
#[error("Serialization error: {0}")]
SerializationError(#[from] serde_json::Error),
#[error("Template error: {0}")]
TemplateError(String),
#[error("Execution error: {0}")]
ExecutionError(String),
#[error("Worker error: {0}")]
WorkerError(String),
#[error("Queue error: {0}")]
QueueError(String),
#[error("Script error: {0}")]
ScriptError(String),
#[error("Watch folder error: {0}")]
WatchError(String),
#[error("API error: {0}")]
ApiError(String),
#[error("Validation error: {0}")]
ValidationError(String),
#[error("Job dependency error: {0}")]
DependencyError(String),
#[error("Resource allocation error: {0}")]
ResourceError(String),
#[error("Retry attempts exhausted for job: {0}")]
RetryExhausted(String),
#[error("Job cancelled: {0}")]
Cancelled(String),
#[error("Operation timeout: {0}")]
Timeout(String),
#[error("Pattern matching error: {0}")]
PatternError(String),
#[error("File operation error: {0}")]
FileOperationError(String),
#[error("Media operation error: {0}")]
MediaOperationError(String),
#[error("Integration error: {0}")]
IntegrationError(String),
}
#[cfg(all(not(target_arch = "wasm32"), feature = "scripting"))]
impl From<mlua::Error> for BatchError {
fn from(err: mlua::Error) -> Self {
Self::ScriptError(err.to_string())
}
}
#[cfg(not(target_arch = "wasm32"))]
impl From<notify::Error> for BatchError {
fn from(err: notify::Error) -> Self {
Self::WatchError(err.to_string())
}
}
impl From<regex::Error> for BatchError {
fn from(err: regex::Error) -> Self {
Self::PatternError(err.to_string())
}
}
impl From<glob::PatternError> for BatchError {
fn from(err: glob::PatternError) -> Self {
Self::PatternError(err.to_string())
}
}
#[cfg(all(not(target_arch = "wasm32"), feature = "sqlite"))]
impl From<r2d2::Error> for BatchError {
fn from(err: r2d2::Error) -> Self {
Self::FileOperationError(format!("Connection pool error: {err}"))
}
}
impl From<walkdir::Error> for BatchError {
fn from(err: walkdir::Error) -> Self {
Self::FileOperationError(err.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = BatchError::JobNotFound("test-job".to_string());
assert_eq!(err.to_string(), "Job not found: test-job");
}
#[test]
fn test_invalid_config_error() {
let err = BatchError::InvalidJobConfig("missing field".to_string());
assert!(err.to_string().contains("Invalid job configuration"));
}
#[test]
fn test_template_error() {
let err = BatchError::TemplateError("invalid syntax".to_string());
assert!(err.to_string().contains("Template error"));
}
#[test]
fn test_execution_error() {
let err = BatchError::ExecutionError("worker failed".to_string());
assert!(err.to_string().contains("Execution error"));
}
#[test]
fn test_retry_exhausted() {
let err = BatchError::RetryExhausted("job-123".to_string());
assert!(err.to_string().contains("Retry attempts exhausted"));
}
#[test]
fn test_cancelled() {
let err = BatchError::Cancelled("job-456".to_string());
assert!(err.to_string().contains("Job cancelled"));
}
#[test]
fn test_timeout() {
let err = BatchError::Timeout("operation took too long".to_string());
assert!(err.to_string().contains("Operation timeout"));
}
}