dogy_backend_api/service/users/error.rs
1//! This module contains the error types for users in axum handlers.
2//!
3//! This follows the rust-10x production code convention for handling errors.
4//! See [this video](https://www.youtube.com/watch?v=j-VQCYP7wyw) to know more about it.
5
6use serde::Serialize;
7use serde_with::{serde_as, DisplayFromStr};
8use sqlx::Error as SqlxError;
9
10//pub type Result<T> = core::result::Result<T, Error>;
11
12/// Error types for users in axum handlers.
13#[serde_as]
14#[derive(Debug, Serialize)]
15pub enum Error {
16 /// This error will occur if a user tries to create a new user with an existing `user_id`.
17 UserAlreadyExists,
18
19 /// This error wraps [`sqlx::Error`] for the error codes that haven't been map.
20 ///
21 /// Serves as a fallback error if in case an unknown error with no mapping occurs.
22 Sqlx(#[serde_as(as = "DisplayFromStr")] sqlx::Error),
23}
24
25impl From<SqlxError> for Error {
26 /// Maps generic sqlx errors into a user-defined error type. Otherwise, just return generic
27 /// sqlx error as a `String`.
28 fn from(err: SqlxError) -> Self {
29 if let SqlxError::Database(db_err) = &err {
30 if let Some(code) = db_err.code() {
31 match code.as_ref() {
32 "23505" => Error::UserAlreadyExists,
33 //"23503" => Error::Sqlx(SqlxError::Database(DatabaseError::ForeignKeyViolation)),
34 _ => Error::Sqlx(err),
35 }
36 } else {
37 Error::Sqlx(err)
38 }
39 } else {
40 Error::Sqlx(err)
41 }
42 }
43}
44
45// Boilerplate for Errors
46impl core::fmt::Display for Error {
47 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
48 write!(fmt, "{self:?}")
49 }
50}
51
52impl std::error::Error for Error {}