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
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
75pub type Result<T> = std::result::Result<T, AllSourceError>;
77
78impl 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}