autopush_common/db/
error.rs1use actix_web::http::StatusCode;
2use serde_json::Error as Serde_Error;
3
4use thiserror::Error;
5
6#[cfg(feature = "bigtable")]
7use crate::db::bigtable::BigTableError;
8use crate::errors::ReportableError;
9
10pub type DbResult<T> = Result<T, DbError>;
11
12#[derive(Debug, Error)]
13pub enum DbError {
14 #[error("Error while performing (de)serialization: {0}")]
15 Serialization(String),
16
17 #[error("Error deserializing to u64: {0}")]
18 DeserializeU64(String),
19
20 #[error("Error deserializing to String: {0}")]
21 DeserializeString(String),
22
23 #[error("Unable to determine table status")]
24 TableStatusUnknown,
25
26 #[cfg(feature = "bigtable")]
27 #[error("BigTable error: {0}")]
28 BTError(#[from] BigTableError),
29
30 #[cfg(feature = "redis")]
31 #[error("Redis error {0}")]
32 RedisError(#[from] redis::RedisError),
33
34 #[error("Serde Parse Error {0}")]
35 SerdeError(#[from] Serde_Error),
36
37 #[error("Connection failure: {0}")]
38 ConnectionError(String),
39
40 #[error("The conditional request failed")]
41 Conditional,
42
43 #[error("Database integrity error: {}", _0)]
44 Integrity(String, Option<String>),
45
46 #[error("Unknown Database Error: {0}")]
47 General(String),
48
49 #[error("Process pending, please wait.")]
51 Backoff(String),
52
53 #[cfg(feature = "postgres")]
54 #[error("Postgres General Error: {0}")]
55 PgGeneralError(String),
56
57 #[cfg(feature = "postgres")]
58 #[error("Postgres Pool Error: {0}")]
59 PgPoolError(#[from] deadpool::managed::PoolError<tokio_postgres::Error>),
60
61 #[cfg(feature = "postgres")]
62 #[error("Postgres Error: {0}")]
63 PgError(#[from] tokio_postgres::Error),
64
65 #[cfg(feature = "postgres")]
66 #[error("Postgres DB Error: {0}")]
67 PgDbError(String),
68}
69
70impl DbError {
71 pub fn status(&self) -> StatusCode {
72 match self {
73 #[cfg(feature = "bigtable")]
74 Self::BTError(e) => e.status(),
75 Self::Backoff(_) => StatusCode::SERVICE_UNAVAILABLE,
76 _ => StatusCode::INTERNAL_SERVER_ERROR,
77 }
78 }
79}
80
81impl ReportableError for DbError {
82 fn reportable_source(&self) -> Option<&(dyn ReportableError + 'static)> {
83 match &self {
84 #[cfg(feature = "bigtable")]
85 DbError::BTError(e) => Some(e),
86 _ => None,
87 }
88 }
89
90 fn is_sentry_event(&self) -> bool {
91 match &self {
92 #[cfg(feature = "bigtable")]
93 DbError::BTError(e) => e.is_sentry_event(),
94 #[cfg(feature = "postgres")]
95 DbError::PgError(_) => true,
96 #[cfg(feature = "postgres")]
97 DbError::PgPoolError(_) => true,
98 #[cfg(feature = "postgres")]
99 DbError::PgDbError(_) => true,
100 _ => false,
101 }
102 }
103
104 fn metric_label(&self) -> Option<&'static str> {
105 match &self {
106 #[cfg(feature = "bigtable")]
107 DbError::BTError(e) => e.metric_label(),
108 DbError::Backoff(_) => Some("storage.error.backoff"),
109 _ => None,
110 }
111 }
112
113 fn extras(&self) -> Vec<(&str, String)> {
114 match &self {
115 #[cfg(feature = "bigtable")]
116 DbError::BTError(e) => e.extras(),
117 DbError::Backoff(e) => {
118 vec![("raw", e.to_string())]
119 }
120 DbError::Integrity(_, Some(row)) => vec![("row", row.clone())],
121 #[cfg(feature = "postgres")]
122 DbError::PgError(e) => vec![(
123 "error",
124 e.as_db_error()
125 .map(|e| e.message().to_owned())
126 .unwrap_or("No error message".to_owned()),
127 )],
128 #[cfg(feature = "postgres")]
129 DbError::PgDbError(v) => vec![("error", v.to_owned())],
130 _ => vec![],
131 }
132 }
133}