allsource_core/
error.rs

1use axum::http::StatusCode;
2use axum::response::{IntoResponse, Response};
3
4/// AllSource error types
5#[derive(Debug, thiserror::Error)]
6pub enum AllSourceError {
7    #[error("Event not found: {0}")]
8    EventNotFound(String),
9
10    #[error("Entity not found: {0}")]
11    EntityNotFound(String),
12
13    #[error("Tenant already exists: {0}")]
14    TenantAlreadyExists(String),
15
16    #[error("Tenant not found: {0}")]
17    TenantNotFound(String),
18
19    #[error("Invalid event: {0}")]
20    InvalidEvent(String),
21
22    #[error("Invalid query: {0}")]
23    InvalidQuery(String),
24
25    #[error("Invalid input: {0}")]
26    InvalidInput(String),
27
28    #[error("Storage error: {0}")]
29    StorageError(String),
30
31    #[error("Serialization error: {0}")]
32    SerializationError(#[from] serde_json::Error),
33
34    #[error("Arrow error: {0}")]
35    ArrowError(String),
36
37    #[error("Index error: {0}")]
38    IndexError(String),
39
40    #[error("Validation error: {0}")]
41    ValidationError(String),
42
43    #[error("Concurrency error: {0}")]
44    ConcurrencyError(String),
45
46    #[error("Queue full: {0}")]
47    QueueFull(String),
48
49    #[error("Internal error: {0}")]
50    InternalError(String),
51}
52
53// Alias for domain layer convenience
54pub use AllSourceError as Error;
55
56impl From<arrow::error::ArrowError> for AllSourceError {
57    fn from(err: arrow::error::ArrowError) -> Self {
58        AllSourceError::ArrowError(err.to_string())
59    }
60}
61
62impl From<parquet::errors::ParquetError> for AllSourceError {
63    fn from(err: parquet::errors::ParquetError) -> Self {
64        AllSourceError::StorageError(err.to_string())
65    }
66}
67
68#[cfg(feature = "postgres")]
69impl From<sqlx::Error> for AllSourceError {
70    fn from(err: sqlx::Error) -> Self {
71        AllSourceError::StorageError(format!("Database error: {}", err))
72    }
73}
74
75/// Custom Result type for AllSource operations
76pub type Result<T> = std::result::Result<T, AllSourceError>;
77
78/// Implement IntoResponse for axum error handling
79impl IntoResponse for AllSourceError {
80    fn into_response(self) -> Response {
81        let (status, error_message) = match self {
82            AllSourceError::EventNotFound(_)
83            | AllSourceError::EntityNotFound(_)
84            | AllSourceError::TenantNotFound(_) => {
85                (StatusCode::NOT_FOUND, self.to_string())
86            }
87            AllSourceError::InvalidEvent(_)
88            | AllSourceError::InvalidQuery(_)
89            | AllSourceError::InvalidInput(_)
90            | AllSourceError::ValidationError(_) => {
91                (StatusCode::BAD_REQUEST, self.to_string())
92            }
93            AllSourceError::TenantAlreadyExists(_)
94            | AllSourceError::ConcurrencyError(_) => {
95                (StatusCode::CONFLICT, self.to_string())
96            }
97            AllSourceError::QueueFull(_) => {
98                (StatusCode::SERVICE_UNAVAILABLE, self.to_string())
99            }
100            AllSourceError::StorageError(_)
101            | AllSourceError::ArrowError(_)
102            | AllSourceError::IndexError(_)
103            | AllSourceError::InternalError(_) => {
104                (StatusCode::INTERNAL_SERVER_ERROR, self.to_string())
105            }
106            AllSourceError::SerializationError(_) => {
107                (StatusCode::UNPROCESSABLE_ENTITY, self.to_string())
108            }
109        };
110
111        let body = serde_json::json!({
112            "error": error_message,
113        });
114
115        (status, axum::Json(body)).into_response()
116    }
117}