1use axum::http::StatusCode;
2
3pub type Result<T> = std::result::Result<T, ServerError>;
5
6#[derive(Debug, thiserror::Error)]
8pub enum ServerError {
9 #[error("invalid config: {0}")]
10 InvalidConfig(String),
11 #[error("bad request: {0}")]
12 BadRequest(String),
13 #[error("unauthorized: {0}")]
14 Unauthorized(String),
15 #[error("not found: {0}")]
16 NotFound(String),
17 #[error("conflict: {0}")]
18 Conflict(String),
19 #[error("payload too large: {0}")]
20 PayloadTooLarge(String),
21 #[error("timeout: {0}")]
22 Timeout(String),
23 #[error("session expired: {0}")]
24 SessionExpired(String),
25 #[error("future distributed execution required: {0}")]
26 FutureDistributedExecutionRequired(String),
27 #[error("capability unavailable: {0}")]
28 CapabilityUnavailable(String),
29 #[error("not implemented: {0}")]
30 NotImplemented(String),
31 #[error("restore integrity mismatch: {0}")]
32 RestoreIntegrityMismatch(String),
33 #[error("sql error: {0}")]
34 Sql(#[from] alopex_sql::SqlError),
35 #[error("core error: {0}")]
36 Core(#[from] alopex_core::Error),
37 #[error("catalog error: {0}")]
38 Catalog(#[from] alopex_sql::catalog::CatalogError),
39 #[error("io error: {0}")]
40 Io(#[from] std::io::Error),
41 #[error("internal error: {0}")]
42 Internal(String),
43}
44
45impl ServerError {
46 pub fn status_code(&self) -> StatusCode {
48 match self {
49 Self::InvalidConfig(_) | Self::BadRequest(_) => StatusCode::BAD_REQUEST,
50 Self::Sql(err) if err.code() == "ALOPEX-S001" => StatusCode::CONFLICT,
51 Self::Sql(_) => StatusCode::BAD_REQUEST,
52 Self::Unauthorized(_) => StatusCode::UNAUTHORIZED,
53 Self::NotFound(_) => StatusCode::NOT_FOUND,
54 Self::Conflict(_) => StatusCode::CONFLICT,
55 Self::PayloadTooLarge(_) => StatusCode::PAYLOAD_TOO_LARGE,
56 Self::Timeout(_) => StatusCode::REQUEST_TIMEOUT,
57 Self::SessionExpired(_) => StatusCode::GONE,
58 Self::FutureDistributedExecutionRequired(_) => StatusCode::NOT_IMPLEMENTED,
59 Self::CapabilityUnavailable(_) => StatusCode::SERVICE_UNAVAILABLE,
60 Self::NotImplemented(_) => StatusCode::NOT_IMPLEMENTED,
61 Self::RestoreIntegrityMismatch(_) => StatusCode::CONFLICT,
62 Self::Core(_) | Self::Catalog(_) | Self::Io(_) | Self::Internal(_) => {
63 StatusCode::INTERNAL_SERVER_ERROR
64 }
65 }
66 }
67
68 pub fn error_code(&self) -> String {
70 match self {
71 Self::Sql(err) => err.code().to_string(),
72 Self::InvalidConfig(_) => "INVALID_CONFIG".to_string(),
73 Self::BadRequest(_) => "INVALID_REQUEST".to_string(),
74 Self::Unauthorized(_) => "UNAUTHORIZED".to_string(),
75 Self::NotFound(_) => "NOT_FOUND".to_string(),
76 Self::Conflict(_) => "CONFLICT".to_string(),
77 Self::PayloadTooLarge(_) => "PAYLOAD_TOO_LARGE".to_string(),
78 Self::Timeout(_) => "QUERY_TIMEOUT".to_string(),
79 Self::SessionExpired(_) => "SESSION_EXPIRED".to_string(),
80 Self::FutureDistributedExecutionRequired(_) => {
81 "FUTURE_DISTRIBUTED_EXECUTION_REQUIRED".to_string()
82 }
83 Self::CapabilityUnavailable(_) => "CAPABILITY_UNAVAILABLE".to_string(),
84 Self::NotImplemented(_) => "NOT_IMPLEMENTED".to_string(),
85 Self::RestoreIntegrityMismatch(_) => "RESTORE_INTEGRITY_MISMATCH".to_string(),
86 Self::Core(_) | Self::Catalog(_) | Self::Io(_) | Self::Internal(_) => {
87 "INTERNAL".to_string()
88 }
89 }
90 }
91}