1use axum::http::StatusCode;
2use axum::response::{IntoResponse, Response};
3
4#[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
53pub 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
68impl From<crate::infrastructure::persistence::SimdJsonError> for AllSourceError {
69 fn from(err: crate::infrastructure::persistence::SimdJsonError) -> Self {
70 AllSourceError::SerializationError(serde_json::Error::io(std::io::Error::new(
71 std::io::ErrorKind::InvalidData,
72 err.to_string(),
73 )))
74 }
75}
76
77#[cfg(feature = "postgres")]
78impl From<sqlx::Error> for AllSourceError {
79 fn from(err: sqlx::Error) -> Self {
80 AllSourceError::StorageError(format!("Database error: {}", err))
81 }
82}
83
84pub type Result<T> = std::result::Result<T, AllSourceError>;
86
87impl IntoResponse for AllSourceError {
89 fn into_response(self) -> Response {
90 let (status, error_message) = match self {
91 AllSourceError::EventNotFound(_)
92 | AllSourceError::EntityNotFound(_)
93 | AllSourceError::TenantNotFound(_) => (StatusCode::NOT_FOUND, self.to_string()),
94 AllSourceError::InvalidEvent(_)
95 | AllSourceError::InvalidQuery(_)
96 | AllSourceError::InvalidInput(_)
97 | AllSourceError::ValidationError(_) => (StatusCode::BAD_REQUEST, self.to_string()),
98 AllSourceError::TenantAlreadyExists(_) | AllSourceError::ConcurrencyError(_) => {
99 (StatusCode::CONFLICT, self.to_string())
100 }
101 AllSourceError::QueueFull(_) => (StatusCode::SERVICE_UNAVAILABLE, self.to_string()),
102 AllSourceError::StorageError(_)
103 | AllSourceError::ArrowError(_)
104 | AllSourceError::IndexError(_)
105 | AllSourceError::InternalError(_) => {
106 (StatusCode::INTERNAL_SERVER_ERROR, self.to_string())
107 }
108 AllSourceError::SerializationError(_) => {
109 (StatusCode::UNPROCESSABLE_ENTITY, self.to_string())
110 }
111 };
112
113 let body = serde_json::json!({
114 "error": error_message,
115 });
116
117 (status, axum::Json(body)).into_response()
118 }
119}