//! Error types for data acquisition service use thiserror::Error; /// Result type alias for acquisition operations pub type AcquisitionResult = Result; /// Errors that can occur during data acquisition #[derive(Error, Debug)] pub enum AcquisitionError { /// Network connectivity issues #[error("Network error: {message}")] Network { message: String }, /// Databento API errors #[error("Databento API error: {message}")] DatabentorAPI { message: String }, /// Authentication failures #[error("Authentication failed: {message}")] Authentication { message: String }, /// Rate limiting errors #[error("Rate limit exceeded: {message}")] RateLimit { message: String }, /// Data validation errors #[error("Data validation failed: {message}")] Validation { message: String }, /// Storage/upload errors #[error("Storage error: {message}")] Storage { message: String }, /// Database errors #[error("Database error: {message}")] Database { message: String }, /// Configuration errors #[error("Configuration error: {message}")] Config { message: String }, /// Disk space errors #[error("Disk space exhausted: {message}")] DiskSpace { message: String }, /// Timeout errors #[error("Operation timed out: {message}")] Timeout { message: String }, /// Data corruption detected #[error("Data corruption detected: {message}")] DataCorruption { message: String }, /// Invalid request parameters #[error("Invalid request: {message}")] InvalidRequest { message: String }, /// Job not found #[error("Job not found: {job_id}")] JobNotFound { job_id: String }, /// Generic internal error #[error("Internal error: {message}")] Internal { message: String }, } // Conversions from other error types impl From for AcquisitionError { fn from(err: std::io::Error) -> Self { AcquisitionError::Internal { message: err.to_string(), } } } impl From for AcquisitionError { fn from(err: reqwest::Error) -> Self { if err.is_timeout() { AcquisitionError::Timeout { message: err.to_string(), } } else if err.is_connect() { AcquisitionError::Network { message: err.to_string(), } } else { AcquisitionError::Internal { message: err.to_string(), } } } } impl From for AcquisitionError { fn from(err: storage::StorageError) -> Self { AcquisitionError::Storage { message: err.to_string(), } } } impl From for AcquisitionError { fn from(err: sqlx::Error) -> Self { AcquisitionError::Database { message: err.to_string(), } } } impl From for AcquisitionError { fn from(err: config::ConfigError) -> Self { AcquisitionError::Config { message: err.to_string(), } } } // Convert to tonic Status for gRPC impl From for tonic::Status { fn from(err: AcquisitionError) -> Self { match err { AcquisitionError::InvalidRequest { .. } => { tonic::Status::invalid_argument(err.to_string()) }, AcquisitionError::JobNotFound { .. } => tonic::Status::not_found(err.to_string()), AcquisitionError::Authentication { .. } => { tonic::Status::unauthenticated(err.to_string()) }, AcquisitionError::RateLimit { .. } => { tonic::Status::resource_exhausted(err.to_string()) }, _ => tonic::Status::internal(err.to_string()), } } }