use thiserror::Error;
use crate::{TaskId, InstanceId, NodeId};
pub type Result<T> = std::result::Result<T, PollenError>;
#[derive(Error, Debug)]
pub enum PollenError {
#[error("task not found: {0}")]
TaskNotFound(TaskId),
#[error("task not found: {0}")]
TaskNameNotFound(String),
#[error("task already exists: {0}")]
TaskAlreadyExists(String),
#[error("task instance not found: {0}")]
InstanceNotFound(InstanceId),
#[error("node not found: {0}")]
NodeNotFound(NodeId),
#[error("invalid cron expression: {0}")]
InvalidCron(String),
#[error("invalid schedule: {0}")]
InvalidSchedule(String),
#[error("storage error: {0}")]
Storage(#[from] StorageError),
#[error("transport error: {0}")]
Transport(#[from] TransportError),
#[error("cluster error: {0}")]
Cluster(#[from] ClusterError),
#[error("execution error: {0}")]
Execution(#[from] ExecutionError),
#[error("serialization error: {0}")]
Serialization(String),
#[error("configuration error: {0}")]
Config(String),
#[error("operation cancelled")]
Cancelled,
#[error("operation timed out")]
Timeout,
#[error("internal error: {0}")]
Internal(String),
}
#[derive(Error, Debug)]
pub enum StorageError {
#[error("sqlite error: {0}")]
Sqlite(String),
#[error("transaction failed: {0}")]
TransactionFailed(String),
#[error("version conflict: expected {expected}, found {found}")]
VersionConflict { expected: u64, found: u64 },
#[error("io error: {0}")]
Io(#[from] std::io::Error),
}
#[derive(Error, Debug)]
pub enum TransportError {
#[error("connection failed to {addr}: {reason}")]
ConnectionFailed { addr: String, reason: String },
#[error("connection closed")]
ConnectionClosed,
#[error("send failed: {0}")]
SendFailed(String),
#[error("receive failed: {0}")]
ReceiveFailed(String),
#[error("tls error: {0}")]
Tls(String),
#[error("invalid address: {0}")]
InvalidAddress(String),
}
#[derive(Error, Debug)]
pub enum ClusterError {
#[error("not a cluster member")]
NotMember,
#[error("gossip error: {0}")]
Gossip(String),
#[error("crdt merge error: {0}")]
CrdtMerge(String),
#[error("node unreachable: {0}")]
NodeUnreachable(NodeId),
}
#[derive(Error, Debug)]
pub enum ExecutionError {
#[error("handler not found for task: {0}")]
HandlerNotFound(TaskId),
#[error("handler panicked: {0}")]
HandlerPanic(String),
#[error("task execution timed out after {0:?}")]
Timeout(std::time::Duration),
#[error("max retries ({max}) exceeded")]
MaxRetriesExceeded { max: u32 },
#[error("failed to claim task instance")]
ClaimFailed,
}
impl From<bincode::Error> for PollenError {
fn from(err: bincode::Error) -> Self {
PollenError::Serialization(err.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = PollenError::TaskNotFound(TaskId::new());
assert!(err.to_string().contains("task not found"));
}
}