pollen-types 0.1.0

Shared types for Pollen distributed task scheduler
Documentation
//! Error types for Pollen.

use thiserror::Error;
use crate::{TaskId, InstanceId, NodeId};

/// Result type for Pollen operations.
pub type Result<T> = std::result::Result<T, PollenError>;

/// Main error type for Pollen operations.
#[derive(Error, Debug)]
pub enum PollenError {
    /// Task not found by ID.
    #[error("task not found: {0}")]
    TaskNotFound(TaskId),

    /// Task not found by name.
    #[error("task not found: {0}")]
    TaskNameNotFound(String),

    /// Task already exists.
    #[error("task already exists: {0}")]
    TaskAlreadyExists(String),

    /// Task instance not found.
    #[error("task instance not found: {0}")]
    InstanceNotFound(InstanceId),

    /// Node not found in cluster.
    #[error("node not found: {0}")]
    NodeNotFound(NodeId),

    /// Invalid cron expression.
    #[error("invalid cron expression: {0}")]
    InvalidCron(String),

    /// Invalid schedule configuration.
    #[error("invalid schedule: {0}")]
    InvalidSchedule(String),

    /// Storage error.
    #[error("storage error: {0}")]
    Storage(#[from] StorageError),

    /// Transport error.
    #[error("transport error: {0}")]
    Transport(#[from] TransportError),

    /// Cluster error.
    #[error("cluster error: {0}")]
    Cluster(#[from] ClusterError),

    /// Execution error.
    #[error("execution error: {0}")]
    Execution(#[from] ExecutionError),

    /// Serialization error.
    #[error("serialization error: {0}")]
    Serialization(String),

    /// Configuration error.
    #[error("configuration error: {0}")]
    Config(String),

    /// Operation cancelled.
    #[error("operation cancelled")]
    Cancelled,

    /// Timeout.
    #[error("operation timed out")]
    Timeout,

    /// Internal error.
    #[error("internal error: {0}")]
    Internal(String),
}

/// Storage-specific errors.
#[derive(Error, Debug)]
pub enum StorageError {
    /// SQLite error.
    #[error("sqlite error: {0}")]
    Sqlite(String),

    /// Transaction failed.
    #[error("transaction failed: {0}")]
    TransactionFailed(String),

    /// Optimistic lock conflict.
    #[error("version conflict: expected {expected}, found {found}")]
    VersionConflict { expected: u64, found: u64 },

    /// IO error.
    #[error("io error: {0}")]
    Io(#[from] std::io::Error),
}

/// Transport-specific errors.
#[derive(Error, Debug)]
pub enum TransportError {
    /// Connection failed.
    #[error("connection failed to {addr}: {reason}")]
    ConnectionFailed { addr: String, reason: String },

    /// Connection closed.
    #[error("connection closed")]
    ConnectionClosed,

    /// Send failed.
    #[error("send failed: {0}")]
    SendFailed(String),

    /// Receive failed.
    #[error("receive failed: {0}")]
    ReceiveFailed(String),

    /// TLS error.
    #[error("tls error: {0}")]
    Tls(String),

    /// Address parse error.
    #[error("invalid address: {0}")]
    InvalidAddress(String),
}

/// Cluster-specific errors.
#[derive(Error, Debug)]
pub enum ClusterError {
    /// Not a cluster member.
    #[error("not a cluster member")]
    NotMember,

    /// Gossip protocol error.
    #[error("gossip error: {0}")]
    Gossip(String),

    /// CRDT merge conflict.
    #[error("crdt merge error: {0}")]
    CrdtMerge(String),

    /// Node unreachable.
    #[error("node unreachable: {0}")]
    NodeUnreachable(NodeId),
}

/// Execution-specific errors.
#[derive(Error, Debug)]
pub enum ExecutionError {
    /// Handler not found.
    #[error("handler not found for task: {0}")]
    HandlerNotFound(TaskId),

    /// Handler panicked.
    #[error("handler panicked: {0}")]
    HandlerPanic(String),

    /// Task timeout.
    #[error("task execution timed out after {0:?}")]
    Timeout(std::time::Duration),

    /// Maximum retries exceeded.
    #[error("max retries ({max}) exceeded")]
    MaxRetriesExceeded { max: u32 },

    /// Claim failed.
    #[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"));
    }
}