Skip to content

Commit 6586990

Browse files
authored
refactor: error handling (#87)
1 parent 9d35f59 commit 6586990

File tree

5 files changed

+103
-21
lines changed

5 files changed

+103
-21
lines changed

docs/api-docs.md

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@
315315

316316
## Errors
317317

318-
The possible error codes and description.
318+
### The possible error codes and description
319319

320320
- `authentication_wrong_credentials`: The provided credentials are incorrect.
321321
- `authentication_missing_credentials`: Required authentication credentials are missing.
@@ -334,4 +334,64 @@ The possible error codes and description.
334334
- `database_error`: There was an error with the database operation.
335335
- `redis_error`: There was an error with the Redis operation.
336336

337-
## END
337+
### The possible error kinds and description
338+
339+
- `authentication_error`: An error occurred during the authentication process.
340+
- `resource_not_found`: The requested resource could not be found.
341+
- `validation_error`: There was a validation error with the provided data.
342+
- `database_error`: An error occurred with the database operation.
343+
- `redis_error`: An error occurred with the Redis operation.
344+
345+
### API error response samples
346+
347+
```json
348+
{
349+
"status": 404,
350+
"errors": [
351+
{
352+
"code": "user_not_found",
353+
"kind": "resource_not_found",
354+
"message": "user not found: 12345",
355+
"description": "user with the ID '12345' does not exist in our records",
356+
"detail": { "user_id": "12345" },
357+
"reason": "must be an existing user",
358+
"instance": "/api/v1/users/12345",
359+
"trace_id": "3d2b4f2d00694354a00522fe3bb86158",
360+
"timestamp": "2024-01-19T16:58:34.123+0000",
361+
"help": "please check if the user ID is correct or refer to our documentation at https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md#errors for more information",
362+
"doc_url": "https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md"
363+
}
364+
]
365+
}
366+
```
367+
368+
```json
369+
{
370+
"status": 422,
371+
"errors": [
372+
{
373+
"code": "transfer_insufficient_funds",
374+
"kind": "validation_error",
375+
"message": "source account does not have sufficient funds for the transfer",
376+
"reason": "source account balance must be sufficient to cover the transfer amount",
377+
"instance": "/api/v1/transactions/transfer",
378+
"trace_id": "fbb9fdf5394d4abe8e42b49c3246310b",
379+
"timestamp": "2024-01-19T16:58:35.225+0000",
380+
"help": "please check the source account balance or refer to our documentation at https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md#errors for more information",
381+
"doc_url": "https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md"
382+
},
383+
{
384+
"code": "transfer_destination_account_not_found",
385+
"kind": "validation_error",
386+
"message": "destination account not found: d424cfe9-c042-41db-9a8e-8da5715fea10",
387+
"detail": { "destination_account_id": "d424cfe9-c042-41db-9a8e-8da5715fea10" },
388+
"reason": "must be an existing account",
389+
"instance": "/api/v1/transactions/transfer",
390+
"trace_id": "8a250eaa650943b085934771fb35ba54",
391+
"timestamp": "2024-01-19T16:59:03.124+0000",
392+
"help": "please check if the destination account ID is correct or refer to our documentation at https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md#errors for more information.",
393+
"doc_url": "https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md"
394+
},
395+
]
396+
}
397+
```

src/api/error.rs

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,45 @@ pub const API_DOCUMENT_URL: &str =
3232
// ]
3333
// }
3434
//
35+
// ---
36+
//
3537
// {
3638
// "status": 422,
3739
// "errors": [
3840
// {
39-
// "code": "invalid_email",
41+
// "code": "transfer_insufficient_funds",
4042
// "kind": "validation_error",
41-
// "message": "user email is not valid",
42-
// "description": "validation error in your request",
43-
// "detail": { "email": "xyz@12345" },
44-
// "reason": "must be a valid email address",
45-
// "instance": "/api/v1/users/12345",
43+
// "message": "source account does not have sufficient funds for the transfer",
44+
// "reason": "source account balance must be sufficient to cover the transfer amount",
45+
// "instance": "/api/v1/transactions/transfer",
4646
// "trace_id": "fbb9fdf5394d4abe8e42b49c3246310b",
4747
// "timestamp": "2024-01-19T16:58:35.225+0000",
48-
// "help": "please check if the user email is correct or refer to our documentation at https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md#errors for more information",
48+
// "help": "please check the source account balance or refer to our documentation at https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md#errors for more information",
4949
// "doc_url": "https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md"
5050
// },
5151
// {
52+
// "code": "transfer_destination_account_not_found",
53+
// "kind": "validation_error",
54+
// "message": "destination account not found: d424cfe9-c042-41db-9a8e-8da5715fea10",
55+
// "detail": { "destination_account_id": "d424cfe9-c042-41db-9a8e-8da5715fea10" },
56+
// "reason": "must be an existing account",
57+
// "instance": "/api/v1/transactions/transfer",
58+
// "trace_id": "8a250eaa650943b085934771fb35ba54",
59+
// "timestamp": "2024-01-19T16:59:03.124+0000",
60+
// "help": "please check if the destination account ID is correct or refer to our documentation at https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md#errors for more information.",
61+
// "doc_url": "https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md"
62+
// },
63+
// ]
64+
// }
65+
//
66+
// ---
67+
//
68+
// (Users endpoint can be extended to handle these validations)
69+
//
70+
// {
71+
// "status": 422,
72+
// "errors": [
73+
// {
5274
// "code": "invalid_birthdate",
5375
// "kind": "validation_error",
5476
// "message": "user birthdate is not correct",
@@ -58,13 +80,13 @@ pub const API_DOCUMENT_URL: &str =
5880
// "instance": "/api/v1/users/12345",
5981
// "trace_id": "8a250eaa650943b085934771fb35ba54",
6082
// "timestamp": "2024-01-19T16:59:03.124+0000",
61-
// "help": "please check if the user birthdate is correct or refer to our documentation at https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md#errors for more information."
83+
// "help": "please check if the user birthdate is correct or refer to our documentation at https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md#errors for more information.",
6284
// "doc_url": "https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md"
6385
// },
6486
// {
6587
// "code": "invalid_role",
6688
// "kind": "validation_error",
67-
// "message": "user birthdate is not correct",
89+
// "message": "role not valid",
6890
// "description": "validation error in your request",
6991
// "detail": { role: "superadmin" },
7092
// "reason": "allowed roles: ['customer', 'guest']",
@@ -74,8 +96,7 @@ pub const API_DOCUMENT_URL: &str =
7496
// "help": "please check if the user role is correct or refer to our documentation at https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md#errors for more information",
7597
// "doc_url": "https://github.com/sheroz/axum-rest-api-sample/blob/main/docs/api-docs.md"
7698
// },
77-
// ]
78-
// }
99+
79100
#[derive(Debug, Serialize, Deserialize)]
80101
pub struct APIError {
81102
pub status: u16,
@@ -216,8 +237,8 @@ impl APIErrorEntry {
216237
self
217238
}
218239

219-
pub fn doc_url(mut self, doc_url: &str) -> Self {
220-
self.doc_url = Some(doc_url.to_owned());
240+
pub fn doc_url(mut self) -> Self {
241+
self.doc_url = Some(API_DOCUMENT_URL.to_owned());
221242
self
222243
}
223244
}

src/api/handlers/transaction_handlers.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,23 +128,24 @@ impl From<TransferValidationError> for APIErrorEntry {
128128
TransferValidationError::InsufficientFunds => error
129129
.code(APIErrorCode::TransferInsufficientFunds)
130130
.kind(APIErrorKind::ValidationError)
131-
.description(
132-
"there are insufficient funds in the source account for the transfer".into(),
133-
)
131+
.reason("source account balance must be sufficient to cover the transfer amount")
134132
.trace_id(),
135133
TransferValidationError::SourceAccountNotFound(source_account_id) => error
136134
.code(APIErrorCode::TransferSourceAccountNotFound)
137135
.kind(APIErrorKind::ValidationError)
138136
.detail(serde_json::json!({"source_account_id": source_account_id}))
137+
.reason("must be an existing account")
139138
.trace_id(),
140139
TransferValidationError::DestinationAccountNotFound(destination_account_id) => error
141140
.code(APIErrorCode::TransferDestinationAccountNotFound)
142141
.kind(APIErrorKind::ValidationError)
143142
.detail(serde_json::json!({"destination_account_id": destination_account_id}))
143+
.reason("must be an existing account")
144144
.trace_id(),
145145
TransferValidationError::AccountsAreSame => error
146146
.code(APIErrorCode::TransferAccountsAreSame)
147147
.kind(APIErrorKind::ValidationError)
148+
.reason("source and destination accounts must be different")
148149
.trace_id(),
149150
}
150151
}

src/api/handlers/user_handlers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ impl From<UserError> for APIErrorEntry {
128128
.instance(&format!("/api/v1/users/{}", user_id))
129129
.trace_id()
130130
.help(&format!("please check if the user ID is correct or refer to our documentation at {}#errors for more information", API_DOCUMENT_URL))
131-
.doc_url(API_DOCUMENT_URL)
131+
.doc_url()
132132
}
133133
}
134134
}

src/application/service/transaction_service.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,12 @@ pub enum TransferError {
112112

113113
#[derive(Debug, Error)]
114114
pub enum TransferValidationError {
115-
#[error("insufficient funds")]
115+
#[error("source account does not have sufficient funds for the transfer")]
116116
InsufficientFunds,
117117
#[error("source account not found: {0}")]
118118
SourceAccountNotFound(Uuid),
119119
#[error("destination account not found: {0}")]
120120
DestinationAccountNotFound(Uuid),
121-
#[error("source and destination accounts must be different")]
121+
#[error("source and destination accounts are the same")]
122122
AccountsAreSame,
123123
}

0 commit comments

Comments
 (0)