batata-consul-client 0.0.2

Rust client for HashiCorp Consul or batata
Documentation
use thiserror::Error;

/// Result type alias for Consul client operations
pub type Result<T> = std::result::Result<T, ConsulError>;

/// Error types for Consul client operations
#[derive(Error, Debug)]
pub enum ConsulError {
    /// HTTP request error
    #[error("HTTP request error: {0}")]
    HttpError(#[from] reqwest::Error),

    /// URL parsing error
    #[error("URL parsing error: {0}")]
    UrlError(#[from] url::ParseError),

    /// JSON serialization/deserialization error
    #[error("JSON error: {0}")]
    JsonError(#[from] serde_json::Error),

    /// API error returned by Consul
    #[error("Consul API error: {status} - {message}")]
    ApiError { status: u16, message: String },

    /// Key not found in KV store
    #[error("Key not found: {0}")]
    KeyNotFound(String),

    /// Session not found
    #[error("Session not found: {0}")]
    SessionNotFound(String),

    /// ACL permission denied
    #[error("ACL permission denied: {0}")]
    PermissionDenied(String),

    /// Invalid configuration
    #[error("Invalid configuration: {0}")]
    InvalidConfig(String),

    /// TLS configuration error
    #[error("TLS error: {0}")]
    TlsError(String),

    /// Timeout error
    #[error("Request timeout")]
    Timeout,

    /// CAS (Check-And-Set) operation failed
    #[error("CAS operation failed")]
    CasFailed,

    /// Lock acquisition failed
    #[error("Lock acquisition failed")]
    LockFailed,

    /// Invalid response from server
    #[error("Invalid response: {0}")]
    InvalidResponse(String),

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

impl ConsulError {
    /// Create an API error from status code and message
    pub fn api_error(status: u16, message: impl Into<String>) -> Self {
        ConsulError::ApiError {
            status,
            message: message.into(),
        }
    }

    /// Check if the error is retryable
    pub fn is_retryable(&self) -> bool {
        matches!(
            self,
            ConsulError::HttpError(_) | ConsulError::Timeout
        )
    }

    /// Check if the error is a "not found" error
    pub fn is_not_found(&self) -> bool {
        matches!(
            self,
            ConsulError::KeyNotFound(_) | ConsulError::SessionNotFound(_)
        ) || matches!(self, ConsulError::ApiError { status, .. } if *status == 404)
    }
}