1pub mod axum_error;
2
3use crate::prelude::StringExt;
4use http::StatusCode;
5use mongodb::error::WriteFailure;
6use serde::Serialize;
7use serde_json::{json, Value};
8use std::convert::AsRef;
9use std::{
10 error::Error as StdError,
11 fmt::{Debug, Display, Formatter, Result as FmtResult},
12 sync::Arc,
13};
14use strum::AsRefStr;
15use thiserror::Error as ThisError;
16
17pub trait ErrorMeta {
18 fn code(&self) -> ErrorCode;
19 fn key(&self) -> ErrorKey;
20 fn message(&self) -> ErrorMessage;
21 fn meta(&self) -> Option<Value>;
22}
23
24#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize)]
25pub struct ErrorCode(u16);
26
27impl ErrorCode {
28 pub fn as_u16(&self) -> u16 {
29 self.0
30 }
31}
32
33impl Display for ErrorCode {
34 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
35 write!(f, "{}", self.0)
36 }
37}
38
39#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize)]
40pub struct ErrorKey(String);
41
42impl ErrorKey {
43 pub fn internal(key: &str, subtype: Option<&str>) -> Self {
44 if let Some(subtype) = subtype {
45 ErrorKey(format!("err::internal::{}::{}", key, subtype))
46 } else {
47 ErrorKey(format!("err::internal::{}", key))
48 }
49 }
50
51 pub fn application(key: &str, subtype: Option<&str>) -> Self {
52 if let Some(subtype) = subtype {
53 ErrorKey(format!("err::application::{}::{}", key, subtype))
54 } else {
55 ErrorKey(format!("err::application::{}", key))
56 }
57 }
58}
59
60impl Display for ErrorKey {
61 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
62 write!(f, "{}", self.0)
63 }
64}
65
66#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize)]
67pub struct ErrorMessage(String);
68
69impl AsRef<str> for ErrorMessage {
70 fn as_ref(&self) -> &str {
71 &self.0
72 }
73}
74
75impl Display for ErrorMessage {
76 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
77 write!(f, "{}", self.0)
78 }
79}
80
81#[derive(ThisError, Clone, Eq, PartialEq, Serialize, AsRefStr)]
82#[serde(rename_all = "camelCase")]
83#[strum(serialize_all = "PascalCase")]
84pub enum InternalError {
85 #[error("An unknown error occurred: {}", .message)]
86 UnknownError {
87 message: String,
88 subtype: Option<String>,
89 meta: Option<Value>,
90 },
91 #[error("A unique field violation occurred: {}", .message)]
92 UniqueFieldViolation {
93 message: String,
94 subtype: Option<String>,
95 meta: Option<Value>,
96 },
97 #[error("A timeout occurred: {}", .message)]
98 Timeout {
99 message: String,
100 subtype: Option<String>,
101 meta: Option<Value>,
102 },
103 #[error("A connection error occurred: {}", .message)]
104 ConnectionError {
105 message: String,
106 subtype: Option<String>,
107 meta: Option<Value>,
108 },
109 #[error("Entity not found: {}", .message)]
110 KeyNotFound {
111 message: String,
112 subtype: Option<String>,
113 meta: Option<Value>,
114 },
115 #[error("Argument provided is invalid: {}", .message)]
116 InvalidArgument {
117 message: String,
118 subtype: Option<String>,
119 meta: Option<Value>,
120 },
121 #[error("An error while performing an IO operation: {}", .message)]
122 IOErr {
123 message: String,
124 subtype: Option<String>,
125 meta: Option<Value>,
126 },
127 #[error("Encription error: {}", .message)]
128 EncryptionError {
129 message: String,
130 subtype: Option<String>,
131 meta: Option<Value>,
132 },
133 #[error("Decryption error: {}", .message)]
134 DecryptionError {
135 message: String,
136 subtype: Option<String>,
137 meta: Option<Value>,
138 },
139 #[error("Configuration error: {}", .message)]
140 ConfigurationError {
141 message: String,
142 subtype: Option<String>,
143 meta: Option<Value>,
144 },
145 #[error("Serialization error: {}", .message)]
146 SerializeError {
147 message: String,
148 subtype: Option<String>,
149 meta: Option<Value>,
150 },
151 #[error("Deserialization error: {}", .message)]
152 DeserializeError {
153 message: String,
154 subtype: Option<String>,
155 meta: Option<Value>,
156 },
157 #[error("An error occurred running the javascript function: {}", .message)]
158 ScriptError {
159 message: String,
160 subtype: Option<String>,
161 meta: Option<Value>,
162 },
163}
164
165impl From<anyhow::Error> for InternalError {
166 fn from(error: anyhow::Error) -> Self {
167 match error.downcast_ref::<InternalError>() {
168 Some(integration_error) => integration_error.clone(),
169 None => InternalError::UnknownError {
170 message: error.to_string(),
171 subtype: None,
172 meta: None,
173 },
174 }
175 }
176}
177
178impl InternalError {
179 pub fn unknown(message: &str, subtype: Option<&str>) -> IntegrationOSError {
180 IntegrationOSError::internal(InternalError::UnknownError {
181 message: message.to_string(),
182 subtype: subtype.map(|s| s.to_string().snake_case()),
183 meta: None,
184 })
185 }
186
187 pub fn unique_field_violation(message: &str, subtype: Option<&str>) -> IntegrationOSError {
188 IntegrationOSError::internal(InternalError::UniqueFieldViolation {
189 message: message.to_string(),
190 subtype: subtype.map(|s| s.to_string().snake_case()),
191 meta: None,
192 })
193 }
194
195 pub fn timeout(message: &str, subtype: Option<&str>) -> IntegrationOSError {
196 IntegrationOSError::internal(InternalError::Timeout {
197 message: message.to_string(),
198 subtype: subtype.map(|s| s.to_string().snake_case()),
199 meta: None,
200 })
201 }
202
203 pub fn script_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
204 IntegrationOSError::internal(InternalError::ScriptError {
205 message: message.to_string(),
206 subtype: subtype.map(|s| s.to_string().snake_case()),
207 meta: None,
208 })
209 }
210
211 pub fn serialize_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
212 IntegrationOSError::internal(InternalError::SerializeError {
213 message: message.to_string(),
214 subtype: subtype.map(|s| s.to_string().snake_case()),
215 meta: None,
216 })
217 }
218
219 pub fn deserialize_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
220 IntegrationOSError::internal(InternalError::DeserializeError {
221 message: message.to_string(),
222 subtype: subtype.map(|s| s.to_string().snake_case()),
223 meta: None,
224 })
225 }
226
227 pub fn configuration_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
228 IntegrationOSError::internal(InternalError::ConfigurationError {
229 message: message.to_string(),
230 subtype: subtype.map(|s| s.to_string().snake_case()),
231 meta: None,
232 })
233 }
234
235 pub fn encryption_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
236 IntegrationOSError::internal(InternalError::EncryptionError {
237 message: message.to_string(),
238 subtype: subtype.map(|s| s.to_string().snake_case()),
239 meta: None,
240 })
241 }
242
243 pub fn decryption_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
244 IntegrationOSError::internal(InternalError::DecryptionError {
245 message: message.to_string(),
246 subtype: subtype.map(|s| s.to_string().snake_case()),
247 meta: None,
248 })
249 }
250
251 pub fn connection_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
252 IntegrationOSError::internal(InternalError::ConnectionError {
253 message: message.to_string(),
254 subtype: subtype.map(|s| s.to_string().snake_case()),
255 meta: None,
256 })
257 }
258
259 pub fn io_err(message: &str, subtype: Option<&str>) -> IntegrationOSError {
260 IntegrationOSError::internal(InternalError::IOErr {
261 message: message.to_string(),
262 subtype: subtype.map(|s| s.to_string().snake_case()),
263 meta: None,
264 })
265 }
266
267 pub fn key_not_found(message: &str, subtype: Option<&str>) -> IntegrationOSError {
268 IntegrationOSError::internal(InternalError::KeyNotFound {
269 message: message.to_string(),
270 subtype: subtype.map(|s| s.to_string().snake_case()),
271 meta: None,
272 })
273 }
274
275 pub fn invalid_argument(message: &str, subtype: Option<&str>) -> IntegrationOSError {
276 IntegrationOSError::internal(InternalError::InvalidArgument {
277 message: message.to_string(),
278 subtype: subtype.map(|s| s.to_string().snake_case()),
279 meta: None,
280 })
281 }
282
283 fn set_meta(self, metadata: Value) -> Self {
284 match self {
285 InternalError::UnknownError {
286 message, subtype, ..
287 } => InternalError::UnknownError {
288 message,
289 subtype,
290 meta: Some(metadata),
291 },
292 InternalError::UniqueFieldViolation {
293 message, subtype, ..
294 } => InternalError::UniqueFieldViolation {
295 message,
296 subtype,
297 meta: Some(metadata),
298 },
299 InternalError::Timeout {
300 message, subtype, ..
301 } => InternalError::Timeout {
302 message,
303 subtype,
304 meta: Some(metadata),
305 },
306 InternalError::ConnectionError {
307 message, subtype, ..
308 } => InternalError::ConnectionError {
309 message,
310 subtype,
311 meta: Some(metadata),
312 },
313 InternalError::KeyNotFound {
314 message, subtype, ..
315 } => InternalError::KeyNotFound {
316 message,
317 subtype,
318 meta: Some(metadata),
319 },
320 InternalError::InvalidArgument {
321 message, subtype, ..
322 } => InternalError::InvalidArgument {
323 message,
324 subtype,
325 meta: Some(metadata),
326 },
327 InternalError::IOErr {
328 message, subtype, ..
329 } => InternalError::IOErr {
330 message,
331 subtype,
332 meta: Some(metadata),
333 },
334 InternalError::EncryptionError {
335 message, subtype, ..
336 } => InternalError::EncryptionError {
337 message,
338 subtype,
339 meta: Some(metadata),
340 },
341 InternalError::DecryptionError {
342 message, subtype, ..
343 } => InternalError::DecryptionError {
344 message,
345 subtype,
346 meta: Some(metadata),
347 },
348 InternalError::ConfigurationError {
349 message, subtype, ..
350 } => InternalError::ConfigurationError {
351 message,
352 subtype,
353 meta: Some(metadata),
354 },
355 InternalError::ScriptError {
356 message, subtype, ..
357 } => InternalError::ScriptError {
358 message,
359 subtype,
360 meta: Some(metadata),
361 },
362 InternalError::SerializeError {
363 message, subtype, ..
364 } => InternalError::SerializeError {
365 message,
366 subtype,
367 meta: Some(metadata),
368 },
369 InternalError::DeserializeError {
370 message, subtype, ..
371 } => InternalError::DeserializeError {
372 message,
373 subtype,
374 meta: Some(metadata),
375 },
376 }
377 }
378}
379
380impl ErrorMeta for InternalError {
381 fn code(&self) -> ErrorCode {
382 match self {
383 InternalError::UnknownError { .. } => ErrorCode(1000),
384 InternalError::UniqueFieldViolation { .. } => ErrorCode(1001),
385 InternalError::Timeout { .. } => ErrorCode(1002),
386 InternalError::ConnectionError { .. } => ErrorCode(1003),
387 InternalError::KeyNotFound { .. } => ErrorCode(1004),
388 InternalError::InvalidArgument { .. } => ErrorCode(1005),
389 InternalError::IOErr { .. } => ErrorCode(1006),
390 InternalError::EncryptionError { .. } => ErrorCode(1007),
391 InternalError::DecryptionError { .. } => ErrorCode(1008),
392 InternalError::ConfigurationError { .. } => ErrorCode(1009),
393 InternalError::ScriptError { .. } => ErrorCode(1010),
394 InternalError::SerializeError { .. } => ErrorCode(1011),
395 InternalError::DeserializeError { .. } => ErrorCode(1012),
396 }
397 }
398
399 fn key(&self) -> ErrorKey {
400 match self {
401 InternalError::UnknownError { subtype, .. } => {
402 ErrorKey::internal("unknown", subtype.as_deref())
403 }
404 InternalError::UniqueFieldViolation { subtype, .. } => {
405 ErrorKey::internal("unique_violation", subtype.as_deref())
406 }
407 InternalError::Timeout { subtype, .. } => {
408 ErrorKey::internal("timeout", subtype.as_deref())
409 }
410 InternalError::ConnectionError { subtype, .. } => {
411 ErrorKey::internal("connection_error", subtype.as_deref())
412 }
413 InternalError::KeyNotFound { subtype, .. } => {
414 ErrorKey::internal("key_not_found", subtype.as_deref())
415 }
416 InternalError::InvalidArgument { subtype, .. } => {
417 ErrorKey::internal("invalid_argument", subtype.as_deref())
418 }
419 InternalError::IOErr { subtype, .. } => {
420 ErrorKey::internal("io_err", subtype.as_deref())
421 }
422 InternalError::EncryptionError { subtype, .. } => {
423 ErrorKey::internal("encryption_error", subtype.as_deref())
424 }
425 InternalError::DecryptionError { subtype, .. } => {
426 ErrorKey::internal("decryption_error", subtype.as_deref())
427 }
428 InternalError::ConfigurationError { subtype, .. } => {
429 ErrorKey::internal("configuration_error", subtype.as_deref())
430 }
431 InternalError::ScriptError { subtype, .. } => {
432 ErrorKey::internal("script_error", subtype.as_deref())
433 }
434 InternalError::SerializeError { subtype, .. } => {
435 ErrorKey::internal("serialize_error", subtype.as_deref())
436 }
437 InternalError::DeserializeError { subtype, .. } => {
438 ErrorKey::internal("deserialize_error", subtype.as_deref())
439 }
440 }
441 }
442
443 fn message(&self) -> ErrorMessage {
444 match self {
445 InternalError::UnknownError { message, .. } => ErrorMessage(message.to_string()),
446 InternalError::UniqueFieldViolation { message, .. } => {
447 ErrorMessage(message.to_string())
448 }
449 InternalError::Timeout { message, .. } => ErrorMessage(message.to_string()),
450 InternalError::ConnectionError { message, .. } => ErrorMessage(message.to_string()),
451 InternalError::KeyNotFound { message, .. } => ErrorMessage(message.to_string()),
452 InternalError::InvalidArgument { message, .. } => ErrorMessage(message.to_string()),
453 InternalError::IOErr { message, .. } => ErrorMessage(message.to_string()),
454 InternalError::EncryptionError { message, .. } => ErrorMessage(message.to_string()),
455 InternalError::DecryptionError { message, .. } => ErrorMessage(message.to_string()),
456 InternalError::ConfigurationError { message, .. } => ErrorMessage(message.to_string()),
457 InternalError::ScriptError { message, .. } => ErrorMessage(message.to_string()),
458 InternalError::SerializeError { message, .. } => ErrorMessage(message.to_string()),
459 InternalError::DeserializeError { message, .. } => ErrorMessage(message.to_string()),
460 }
461 }
462
463 fn meta(&self) -> Option<Value> {
465 match self {
466 InternalError::UnknownError { meta, .. } => meta.clone(),
467 InternalError::UniqueFieldViolation { meta, .. } => meta.clone(),
468 InternalError::Timeout { meta, .. } => meta.clone(),
469 InternalError::ConnectionError { meta, .. } => meta.clone(),
470 InternalError::KeyNotFound { meta, .. } => meta.clone(),
471 InternalError::InvalidArgument { meta, .. } => meta.clone(),
472 InternalError::IOErr { meta, .. } => meta.clone(),
473 InternalError::EncryptionError { meta, .. } => meta.clone(),
474 InternalError::DecryptionError { meta, .. } => meta.clone(),
475 InternalError::ConfigurationError { meta, .. } => meta.clone(),
476 InternalError::ScriptError { meta, .. } => meta.clone(),
477 InternalError::SerializeError { meta, .. } => meta.clone(),
478 InternalError::DeserializeError { meta, .. } => meta.clone(),
479 }
480 }
481}
482
483impl Debug for InternalError {
484 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
485 writeln!(f, "{}\n", &self)?;
486 let mut current = self.source();
487
488 while let Some(cause) = current {
489 writeln!(f, "Caused by:\n\t{}", cause)?;
490 current = cause.source();
491 }
492
493 Ok(())
494 }
495}
496
497#[derive(ThisError, Clone, Eq, PartialEq, Serialize, AsRefStr)]
498#[serde(rename_all = "camelCase")]
499#[strum(serialize_all = "PascalCase")]
500pub enum ApplicationError {
501 #[error("Bad Request: {}", .message)]
502 BadRequest {
503 message: String,
504 subtype: Option<String>,
505 meta: Option<Value>,
506 },
507 #[error("Conflict: {}", .message)]
508 Conflict {
509 message: String,
510 subtype: Option<String>,
511 meta: Option<Value>,
512 },
513 #[error("Forbidden: {}", .message)]
514 Forbidden {
515 message: String,
516 subtype: Option<String>,
517 meta: Option<Value>,
518 },
519 #[error("Internal Server Error: {}", .message)]
520 InternalServerError {
521 message: String,
522 subtype: Option<String>,
523 meta: Option<Value>,
524 },
525 #[error("Method Not Allowed: {}", .message)]
526 MethodNotAllowed {
527 message: String,
528 subtype: Option<String>,
529 meta: Option<Value>,
530 },
531 #[error("Not Found: {}", .message)]
532 NotFound {
533 message: String,
534 subtype: Option<String>,
535 meta: Option<Value>,
536 },
537 #[error("Not Implemented: {}", .message)]
538 NotImplemented {
539 message: String,
540 subtype: Option<String>,
541 meta: Option<Value>,
542 },
543 #[error("Precondition Failed: {}", .message)]
544 FailedDependency {
545 message: String,
546 subtype: Option<String>,
547 meta: Option<Value>,
548 },
549 #[error("Service Unavailable: {}", .message)]
550 ServiceUnavailable {
551 message: String,
552 subtype: Option<String>,
553 meta: Option<Value>,
554 },
555 #[error("Too Many Requests: {}", .message)]
556 TooManyRequests {
557 message: String,
558 subtype: Option<String>,
559 meta: Option<Value>,
560 },
561 #[error("Unauthorized: {}", .message)]
562 Unauthorized {
563 message: String,
564 subtype: Option<String>,
565 meta: Option<Value>,
566 },
567 #[error("Unprocessable Entity: {}", .message)]
568 UnprocessableEntity {
569 message: String,
570 subtype: Option<String>,
571 meta: Option<Value>,
572 },
573}
574
575impl From<anyhow::Error> for ApplicationError {
576 fn from(error: anyhow::Error) -> Self {
577 match error.downcast_ref::<ApplicationError>() {
578 Some(integration_error) => integration_error.clone(),
579 None => ApplicationError::InternalServerError {
580 message: error.to_string(),
581 subtype: None,
582 meta: None,
583 },
584 }
585 }
586}
587
588impl ApplicationError {
589 pub fn bad_request(message: &str, subtype: Option<&str>) -> IntegrationOSError {
590 IntegrationOSError::application(ApplicationError::BadRequest {
591 message: message.to_string(),
592 subtype: subtype.map(|s| s.to_string().snake_case()),
593 meta: None,
594 })
595 }
596
597 pub fn conflict(message: &str, subtype: Option<&str>) -> IntegrationOSError {
598 IntegrationOSError::application(ApplicationError::Conflict {
599 message: message.to_string(),
600 subtype: subtype.map(|s| s.to_string().snake_case()),
601 meta: None,
602 })
603 }
604
605 pub fn forbidden(message: &str, subtype: Option<&str>) -> IntegrationOSError {
606 IntegrationOSError::application(ApplicationError::Forbidden {
607 message: message.to_string(),
608 subtype: subtype.map(|s| s.to_string().snake_case()),
609 meta: None,
610 })
611 }
612
613 pub fn internal_server_error(message: &str, subtype: Option<&str>) -> IntegrationOSError {
614 IntegrationOSError::application(ApplicationError::InternalServerError {
615 message: message.to_string(),
616 subtype: subtype.map(|s| s.to_string().snake_case()),
617 meta: None,
618 })
619 }
620
621 pub fn method_not_allowed(message: &str, subtype: Option<&str>) -> IntegrationOSError {
622 IntegrationOSError::application(ApplicationError::MethodNotAllowed {
623 message: message.to_string(),
624 subtype: subtype.map(|s| s.to_string().snake_case()),
625 meta: None,
626 })
627 }
628
629 pub fn not_found(message: &str, subtype: Option<&str>) -> IntegrationOSError {
630 IntegrationOSError::application(ApplicationError::NotFound {
631 message: message.to_string(),
632 subtype: subtype.map(|s| s.to_string().snake_case()),
633 meta: None,
634 })
635 }
636
637 pub fn not_implemented(message: &str, subtype: Option<&str>) -> IntegrationOSError {
638 IntegrationOSError::application(ApplicationError::NotImplemented {
639 message: message.to_string(),
640 subtype: subtype.map(|s| s.to_string().snake_case()),
641 meta: None,
642 })
643 }
644
645 pub fn failed_dependency(message: &str, subtype: Option<&str>) -> IntegrationOSError {
646 IntegrationOSError::application(ApplicationError::FailedDependency {
647 message: message.to_string(),
648 subtype: subtype.map(|s| s.to_string().snake_case()),
649 meta: None,
650 })
651 }
652
653 pub fn service_unavailable(message: &str, subtype: Option<&str>) -> IntegrationOSError {
654 IntegrationOSError::application(ApplicationError::ServiceUnavailable {
655 message: message.to_string(),
656 subtype: subtype.map(|s| s.to_string().snake_case()),
657 meta: None,
658 })
659 }
660
661 pub fn too_many_requests(message: &str, subtype: Option<&str>) -> IntegrationOSError {
662 IntegrationOSError::application(ApplicationError::TooManyRequests {
663 message: message.to_string(),
664 subtype: subtype.map(|s| s.to_string().snake_case()),
665 meta: None,
666 })
667 }
668
669 pub fn unauthorized(message: &str, subtype: Option<&str>) -> IntegrationOSError {
670 IntegrationOSError::application(ApplicationError::Unauthorized {
671 message: message.to_string(),
672 subtype: subtype.map(|s| s.to_string().snake_case()),
673 meta: None,
674 })
675 }
676
677 pub fn unprocessable_entity(message: &str, subtype: Option<&str>) -> IntegrationOSError {
678 IntegrationOSError::application(ApplicationError::UnprocessableEntity {
679 message: message.to_string(),
680 subtype: subtype.map(|s| s.to_string().snake_case()),
681 meta: None,
682 })
683 }
684
685 fn set_meta(self, meta: Value) -> Self {
686 match self {
687 ApplicationError::BadRequest {
688 message, subtype, ..
689 } => ApplicationError::BadRequest {
690 message: message.clone(),
691 subtype: subtype.clone(),
692 meta: Some(meta),
693 },
694 ApplicationError::Conflict {
695 message, subtype, ..
696 } => ApplicationError::Conflict {
697 message: message.clone(),
698 subtype: subtype.clone(),
699 meta: Some(meta),
700 },
701 ApplicationError::Forbidden {
702 message, subtype, ..
703 } => ApplicationError::Forbidden {
704 message: message.clone(),
705 subtype: subtype.clone(),
706 meta: Some(meta),
707 },
708 ApplicationError::InternalServerError {
709 message, subtype, ..
710 } => ApplicationError::InternalServerError {
711 message: message.clone(),
712 subtype: subtype.clone(),
713 meta: Some(meta),
714 },
715 ApplicationError::MethodNotAllowed {
716 message, subtype, ..
717 } => ApplicationError::MethodNotAllowed {
718 message: message.clone(),
719 subtype: subtype.clone(),
720 meta: Some(meta),
721 },
722 ApplicationError::NotFound {
723 message, subtype, ..
724 } => ApplicationError::NotFound {
725 message: message.clone(),
726 subtype: subtype.clone(),
727 meta: Some(meta),
728 },
729 ApplicationError::NotImplemented {
730 message, subtype, ..
731 } => ApplicationError::NotImplemented {
732 message: message.clone(),
733 subtype: subtype.clone(),
734 meta: Some(meta),
735 },
736 ApplicationError::FailedDependency {
737 message, subtype, ..
738 } => ApplicationError::FailedDependency {
739 message: message.clone(),
740 subtype: subtype.clone(),
741 meta: Some(meta),
742 },
743 ApplicationError::ServiceUnavailable {
744 message, subtype, ..
745 } => ApplicationError::ServiceUnavailable {
746 message: message.clone(),
747 subtype: subtype.clone(),
748 meta: Some(meta),
749 },
750 ApplicationError::TooManyRequests {
751 message, subtype, ..
752 } => ApplicationError::TooManyRequests {
753 message: message.clone(),
754 subtype: subtype.clone(),
755 meta: Some(meta),
756 },
757 ApplicationError::Unauthorized {
758 message, subtype, ..
759 } => ApplicationError::Unauthorized {
760 message: message.clone(),
761 subtype: subtype.clone(),
762 meta: Some(meta),
763 },
764 ApplicationError::UnprocessableEntity {
765 message, subtype, ..
766 } => ApplicationError::UnprocessableEntity {
767 message: message.clone(),
768 subtype: subtype.clone(),
769 meta: Some(meta),
770 },
771 }
772 }
773}
774
775impl ErrorMeta for ApplicationError {
776 fn code(&self) -> ErrorCode {
777 match self {
778 ApplicationError::BadRequest { .. } => ErrorCode(2000),
779 ApplicationError::Conflict { .. } => ErrorCode(2001),
780 ApplicationError::Forbidden { .. } => ErrorCode(2002),
781 ApplicationError::InternalServerError { .. } => ErrorCode(2003),
782 ApplicationError::MethodNotAllowed { .. } => ErrorCode(2004),
783 ApplicationError::NotFound { .. } => ErrorCode(2005),
784 ApplicationError::NotImplemented { .. } => ErrorCode(2006),
785 ApplicationError::FailedDependency { .. } => ErrorCode(2007),
786 ApplicationError::ServiceUnavailable { .. } => ErrorCode(2008),
787 ApplicationError::TooManyRequests { .. } => ErrorCode(2009),
788 ApplicationError::Unauthorized { .. } => ErrorCode(2010),
789 ApplicationError::UnprocessableEntity { .. } => ErrorCode(2011),
790 }
791 }
792
793 fn key(&self) -> ErrorKey {
794 match self {
795 ApplicationError::BadRequest { subtype, .. } => {
796 ErrorKey::application("bad_request", subtype.as_deref())
797 }
798 ApplicationError::Conflict { subtype, .. } => {
799 ErrorKey::application("conflict", subtype.as_deref())
800 }
801 ApplicationError::Forbidden { subtype, .. } => {
802 ErrorKey::application("forbidden", subtype.as_deref())
803 }
804 ApplicationError::InternalServerError { subtype, .. } => {
805 ErrorKey::application("internal_server_error", subtype.as_deref())
806 }
807 ApplicationError::MethodNotAllowed { subtype, .. } => {
808 ErrorKey::application("method_not_allowed", subtype.as_deref())
809 }
810 ApplicationError::NotFound { subtype, .. } => {
811 ErrorKey::application("not_found", subtype.as_deref())
812 }
813 ApplicationError::NotImplemented { subtype, .. } => {
814 ErrorKey::application("not_implemented", subtype.as_deref())
815 }
816 ApplicationError::FailedDependency { subtype, .. } => {
817 ErrorKey::application("failed_dependency", subtype.as_deref())
818 }
819 ApplicationError::ServiceUnavailable { subtype, .. } => {
820 ErrorKey::application("service_unavailable", subtype.as_deref())
821 }
822 ApplicationError::TooManyRequests { subtype, .. } => {
823 ErrorKey::application("too_many_requests", subtype.as_deref())
824 }
825 ApplicationError::Unauthorized { subtype, .. } => {
826 ErrorKey::application("unauthorized", subtype.as_deref())
827 }
828 ApplicationError::UnprocessableEntity { subtype, .. } => {
829 ErrorKey::application("unprocessable_entity", subtype.as_deref())
830 }
831 }
832 }
833
834 fn message(&self) -> ErrorMessage {
835 match self {
836 ApplicationError::BadRequest { message, .. } => ErrorMessage(message.to_string()),
837 ApplicationError::Conflict { message, .. } => ErrorMessage(message.to_string()),
838 ApplicationError::Forbidden { message, .. } => ErrorMessage(message.to_string()),
839 ApplicationError::InternalServerError { message, .. } => {
840 ErrorMessage(message.to_string())
841 }
842 ApplicationError::MethodNotAllowed { message, .. } => ErrorMessage(message.to_string()),
843 ApplicationError::NotFound { message, .. } => ErrorMessage(message.to_string()),
844 ApplicationError::NotImplemented { message, .. } => ErrorMessage(message.to_string()),
845 ApplicationError::FailedDependency { message, .. } => ErrorMessage(message.to_string()),
846 ApplicationError::ServiceUnavailable { message, .. } => {
847 ErrorMessage(message.to_string())
848 }
849 ApplicationError::TooManyRequests { message, .. } => ErrorMessage(message.to_string()),
850 ApplicationError::Unauthorized { message, .. } => ErrorMessage(message.to_string()),
851 ApplicationError::UnprocessableEntity { message, .. } => {
852 ErrorMessage(message.to_string())
853 }
854 }
855 }
856
857 fn meta(&self) -> Option<Value> {
858 match self {
859 ApplicationError::BadRequest { meta, .. } => meta.clone(),
860 ApplicationError::Conflict { meta, .. } => meta.clone(),
861 ApplicationError::Forbidden { meta, .. } => meta.clone(),
862 ApplicationError::InternalServerError { meta, .. } => meta.clone(),
863 ApplicationError::MethodNotAllowed { meta, .. } => meta.clone(),
864 ApplicationError::NotFound { meta, .. } => meta.clone(),
865 ApplicationError::NotImplemented { meta, .. } => meta.clone(),
866 ApplicationError::FailedDependency { meta, .. } => meta.clone(),
867 ApplicationError::ServiceUnavailable { meta, .. } => meta.clone(),
868 ApplicationError::TooManyRequests { meta, .. } => meta.clone(),
869 ApplicationError::Unauthorized { meta, .. } => meta.clone(),
870 ApplicationError::UnprocessableEntity { meta, .. } => meta.clone(),
871 }
872 }
873}
874
875impl Debug for ApplicationError {
876 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
877 writeln!(f, "{}\n", &self)?;
878 let mut current = self.source();
879
880 while let Some(cause) = current {
881 writeln!(f, "Caused by:\n\t{}", cause)?;
882 current = cause.source();
883 }
884
885 Ok(())
886 }
887}
888
889impl From<InternalError> for ApplicationError {
890 fn from(error: InternalError) -> Self {
891 match error {
892 InternalError::Timeout { .. }
893 | InternalError::ConnectionError { .. }
894 | InternalError::IOErr { .. }
895 | InternalError::EncryptionError { .. }
896 | InternalError::DecryptionError { .. }
897 | InternalError::ScriptError { .. }
898 | InternalError::ConfigurationError { .. }
899 | InternalError::UnknownError { .. } => ApplicationError::InternalServerError {
900 message: "An unknown error occurred".into(),
901 subtype: None,
902 meta: None,
903 },
904 InternalError::UniqueFieldViolation {
905 message,
906 subtype,
907 meta,
908 } => ApplicationError::Conflict {
909 message,
910 subtype,
911 meta,
912 },
913 InternalError::KeyNotFound {
914 message,
915 subtype,
916 meta,
917 } => ApplicationError::NotFound {
918 message,
919 subtype,
920 meta,
921 },
922 InternalError::InvalidArgument {
923 message,
924 subtype,
925 meta,
926 }
927 | InternalError::SerializeError {
928 message,
929 subtype,
930 meta,
931 }
932 | InternalError::DeserializeError {
933 message,
934 subtype,
935 meta,
936 } => ApplicationError::BadRequest {
937 message,
938 subtype,
939 meta,
940 },
941 }
942 }
943}
944
945#[derive(ThisError, Debug, Clone, Eq, PartialEq, Serialize)]
946#[serde(untagged)]
947pub enum IntegrationOSError {
948 Internal(InternalError),
949 Application(ApplicationError),
950}
951
952impl AsRef<str> for IntegrationOSError {
953 fn as_ref(&self) -> &str {
954 match self {
955 IntegrationOSError::Internal(e) => e.as_ref(),
956 IntegrationOSError::Application(e) => e.as_ref(),
957 }
958 }
959}
960
961impl From<anyhow::Error> for IntegrationOSError {
962 fn from(error: anyhow::Error) -> Self {
963 match error.downcast_ref::<IntegrationOSError>() {
964 Some(integration_error) => match integration_error {
965 internal @ IntegrationOSError::Internal(_) => internal.clone(),
966 application @ IntegrationOSError::Application(_) => application.clone(),
967 },
968 None => IntegrationOSError::Internal(InternalError::UnknownError {
969 message: error.to_string(),
970 subtype: None,
971 meta: None,
972 }),
973 }
974 }
975}
976
977impl From<Arc<IntegrationOSError>> for IntegrationOSError {
978 fn from(error: Arc<IntegrationOSError>) -> Self {
979 Arc::unwrap_or_clone(error)
980 }
981}
982
983impl<'a> From<&'a IntegrationOSError> for StatusCode {
984 fn from(value: &'a IntegrationOSError) -> Self {
985 match value {
986 IntegrationOSError::Internal(e) => match e {
987 InternalError::UniqueFieldViolation { .. } => StatusCode::CONFLICT,
988 InternalError::Timeout { .. } => StatusCode::GATEWAY_TIMEOUT,
989 InternalError::ConnectionError { .. } => StatusCode::BAD_GATEWAY,
990 InternalError::KeyNotFound { .. } => StatusCode::NOT_FOUND,
991 InternalError::InvalidArgument { .. }
992 | InternalError::SerializeError { .. }
993 | InternalError::DeserializeError { .. } => StatusCode::BAD_REQUEST,
994 InternalError::UnknownError { .. }
995 | InternalError::IOErr { .. }
996 | InternalError::EncryptionError { .. }
997 | InternalError::ConfigurationError { .. }
998 | InternalError::ScriptError { .. }
999 | InternalError::DecryptionError { .. } => StatusCode::INTERNAL_SERVER_ERROR,
1000 },
1001 IntegrationOSError::Application(e) => match e {
1002 ApplicationError::BadRequest { .. } => StatusCode::BAD_REQUEST,
1003 ApplicationError::Conflict { .. } => StatusCode::CONFLICT,
1004 ApplicationError::Forbidden { .. } => StatusCode::FORBIDDEN,
1005 ApplicationError::InternalServerError { .. } => StatusCode::INTERNAL_SERVER_ERROR,
1006 ApplicationError::MethodNotAllowed { .. } => StatusCode::METHOD_NOT_ALLOWED,
1007 ApplicationError::NotFound { .. } => StatusCode::NOT_FOUND,
1008 ApplicationError::NotImplemented { .. } => StatusCode::NOT_IMPLEMENTED,
1009 ApplicationError::FailedDependency { .. } => StatusCode::FAILED_DEPENDENCY,
1010 ApplicationError::ServiceUnavailable { .. } => StatusCode::SERVICE_UNAVAILABLE,
1011 ApplicationError::TooManyRequests { .. } => StatusCode::TOO_MANY_REQUESTS,
1012 ApplicationError::Unauthorized { .. } => StatusCode::UNAUTHORIZED,
1013 ApplicationError::UnprocessableEntity { .. } => StatusCode::UNPROCESSABLE_ENTITY,
1014 },
1015 }
1016 }
1017}
1018
1019impl From<mongodb::error::Error> for IntegrationOSError {
1020 fn from(err: mongodb::error::Error) -> Self {
1021 match *err.kind {
1022 mongodb::error::ErrorKind::InvalidArgument { message, .. } => {
1023 InternalError::invalid_argument(&message, None)
1024 }
1025 mongodb::error::ErrorKind::Authentication { message, .. } => {
1026 InternalError::connection_error(&message, Some("Authentication failed"))
1027 }
1028 mongodb::error::ErrorKind::BsonDeserialization(error) => {
1029 InternalError::invalid_argument(
1030 &error.to_string(),
1031 Some("BSON deserialization error"),
1032 )
1033 }
1034 mongodb::error::ErrorKind::BsonSerialization(error) => InternalError::invalid_argument(
1035 &error.to_string(),
1036 Some("BSON serialization error"),
1037 ),
1038 mongodb::error::ErrorKind::BulkWrite(error) => InternalError::unknown(
1039 &error
1040 .write_errors
1041 .into_iter()
1042 .map(|e| e.into_iter().map(|e| e.message).collect())
1043 .collect::<Vec<String>>()
1044 .join(", "),
1045 Some("Bulk write error"),
1046 ),
1047 mongodb::error::ErrorKind::Command(error) => {
1048 let code = error.code;
1049 if code == 11000 {
1050 InternalError::unique_field_violation(
1051 &error.message,
1052 Some("A document with the same unique key already exists"),
1053 )
1054 } else {
1055 InternalError::unknown(&error.message, Some("Command error"))
1056 }
1057 }
1058 mongodb::error::ErrorKind::DnsResolve { message, .. } => {
1059 InternalError::connection_error(&message, Some("DNS resolution failed"))
1060 }
1061 mongodb::error::ErrorKind::GridFs { .. } => InternalError::unknown(
1062 "GridFS error",
1063 Some("An error occurred while interacting with GridFS"),
1064 ),
1065 mongodb::error::ErrorKind::Internal { message, .. } => {
1066 InternalError::unknown(&message, Some("Internal error"))
1067 }
1068 mongodb::error::ErrorKind::Io(error) => InternalError::io_err(&error.to_string(), None),
1069 mongodb::error::ErrorKind::ConnectionPoolCleared { message, .. } => {
1070 InternalError::connection_error(&message, Some("Connection pool cleared"))
1071 }
1072 mongodb::error::ErrorKind::InvalidResponse { message, .. } => {
1073 InternalError::invalid_argument(&message, Some("Invalid response"))
1074 }
1075 mongodb::error::ErrorKind::ServerSelection { message, .. } => {
1076 InternalError::connection_error(&message, Some("Server selection failed"))
1077 }
1078 mongodb::error::ErrorKind::SessionsNotSupported => {
1079 InternalError::invalid_argument("Sessions not supported", None)
1080 }
1081 mongodb::error::ErrorKind::InvalidTlsConfig { message, .. } => {
1082 InternalError::connection_error(&message, Some("Invalid TLS configuration"))
1083 }
1084 mongodb::error::ErrorKind::Write(error) => match error {
1085 WriteFailure::WriteConcernError(err) => {
1086 let code = err.code;
1087
1088 if code == 11000 {
1089 InternalError::unique_field_violation(
1090 &err.message,
1091 Some("A document with the same unique key already exists"),
1092 )
1093 } else {
1094 InternalError::unknown(&err.message, Some("Write concern error"))
1095 }
1096 }
1097 WriteFailure::WriteError(err) => {
1098 let code = err.code;
1099 if code == 11000 {
1100 InternalError::unique_field_violation(
1101 &err.message,
1102 Some("A document with the same unique key already exists"),
1103 )
1104 } else {
1105 InternalError::unknown(&err.message, Some("Write error"))
1106 }
1107 }
1108 _ => InternalError::unknown("Write error", Some("An error occurred while writing")),
1109 },
1110 mongodb::error::ErrorKind::Transaction { message, .. } => {
1111 InternalError::unknown(&message, Some("Transaction error"))
1112 }
1113 mongodb::error::ErrorKind::IncompatibleServer { message, .. } => {
1114 InternalError::connection_error(&message, Some("Incompatible server"))
1115 }
1116 mongodb::error::ErrorKind::MissingResumeToken => {
1117 InternalError::invalid_argument("Missing resume token", None)
1118 }
1119 mongodb::error::ErrorKind::Custom(_) => InternalError::unknown(
1120 "Unknown error",
1121 Some("An error occurred with the MongoDB driver"),
1122 ),
1123 mongodb::error::ErrorKind::Shutdown => {
1124 InternalError::unknown("Shutdown error", Some("The MongoDB driver has shut down"))
1125 }
1126 _ => InternalError::unknown("Unknown error", Some("An unknown error occurred")),
1127 }
1128 }
1129}
1130
1131impl From<IntegrationOSError> for StatusCode {
1132 fn from(value: IntegrationOSError) -> Self {
1133 (&value).into()
1134 }
1135}
1136
1137impl IntegrationOSError {
1138 pub fn status(&self) -> u16 {
1139 StatusCode::from(self).as_u16()
1140 }
1141
1142 fn internal(internal: InternalError) -> Self {
1143 IntegrationOSError::Internal(internal)
1144 }
1145
1146 fn application(application: ApplicationError) -> Self {
1147 IntegrationOSError::Application(application)
1148 }
1149
1150 pub fn from_err_code(status: StatusCode, message: &str, subtype: Option<&str>) -> Self {
1151 let message = message.to_string();
1152 let subtype = subtype.map(|s| s.to_string());
1153 let meta = None;
1154 match status {
1155 StatusCode::BAD_REQUEST => {
1156 IntegrationOSError::application(ApplicationError::BadRequest {
1157 message,
1158 subtype,
1159 meta,
1160 })
1161 }
1162
1163 StatusCode::CONFLICT => IntegrationOSError::application(ApplicationError::Conflict {
1164 message,
1165 subtype,
1166 meta,
1167 }),
1168
1169 StatusCode::FORBIDDEN => IntegrationOSError::application(ApplicationError::Forbidden {
1170 message,
1171 subtype,
1172 meta,
1173 }),
1174
1175 StatusCode::INTERNAL_SERVER_ERROR => {
1176 IntegrationOSError::application(ApplicationError::InternalServerError {
1177 message,
1178 subtype,
1179 meta,
1180 })
1181 }
1182
1183 StatusCode::METHOD_NOT_ALLOWED => {
1184 IntegrationOSError::application(ApplicationError::MethodNotAllowed {
1185 message,
1186 subtype,
1187 meta,
1188 })
1189 }
1190
1191 StatusCode::NOT_FOUND => IntegrationOSError::application(ApplicationError::NotFound {
1192 message,
1193 subtype,
1194 meta,
1195 }),
1196
1197 StatusCode::NOT_IMPLEMENTED => {
1198 IntegrationOSError::application(ApplicationError::NotImplemented {
1199 message,
1200 subtype,
1201 meta,
1202 })
1203 }
1204
1205 StatusCode::FAILED_DEPENDENCY => {
1206 IntegrationOSError::application(ApplicationError::FailedDependency {
1207 message,
1208 subtype,
1209 meta,
1210 })
1211 }
1212
1213 StatusCode::SERVICE_UNAVAILABLE => {
1214 IntegrationOSError::application(ApplicationError::ServiceUnavailable {
1215 message,
1216 subtype,
1217 meta,
1218 })
1219 }
1220
1221 StatusCode::TOO_MANY_REQUESTS => {
1222 IntegrationOSError::application(ApplicationError::TooManyRequests {
1223 message,
1224 subtype,
1225 meta,
1226 })
1227 }
1228
1229 StatusCode::UNAUTHORIZED => {
1230 IntegrationOSError::application(ApplicationError::Unauthorized {
1231 message,
1232 subtype,
1233 meta,
1234 })
1235 }
1236
1237 StatusCode::UNPROCESSABLE_ENTITY => {
1238 IntegrationOSError::application(ApplicationError::UnprocessableEntity {
1239 message,
1240 subtype,
1241 meta,
1242 })
1243 }
1244
1245 _ => {
1246 if status.is_client_error() {
1247 IntegrationOSError::application(ApplicationError::BadRequest {
1248 message,
1249 subtype,
1250 meta,
1251 })
1252 } else {
1253 IntegrationOSError::internal(InternalError::IOErr {
1254 message: format!(
1255 "Unknown error with status code: {}, message: {}",
1256 status, message
1257 ),
1258 subtype,
1259 meta,
1260 })
1261 }
1262 }
1263 }
1264 }
1265
1266 pub(crate) fn as_application(&self) -> IntegrationOSError {
1267 match self {
1268 IntegrationOSError::Application(e) => IntegrationOSError::Application(e.clone()),
1269 IntegrationOSError::Internal(e) => IntegrationOSError::Application(e.clone().into()),
1270 }
1271 }
1272
1273 pub(crate) fn as_json(&self) -> serde_json::Value {
1274 json!({
1275 "type": self.as_ref(),
1276 "code": self.code().as_u16(),
1277 "status": StatusCode::from(self).as_u16(),
1278 "key": self.key().to_string(),
1279 "message": self.message().to_string(),
1280 "meta": self.meta().unwrap_or_default(),
1281 })
1282 }
1283
1284 pub fn set_meta(self, meta: &Value) -> Self {
1285 match self {
1286 IntegrationOSError::Internal(e) => {
1287 IntegrationOSError::internal(e.set_meta(meta.clone()))
1288 }
1289 IntegrationOSError::Application(e) => {
1290 IntegrationOSError::application(e.set_meta(meta.clone()))
1291 }
1292 }
1293 }
1294
1295 pub fn is_internal(&self) -> bool {
1296 matches!(self, IntegrationOSError::Internal(_))
1297 }
1298
1299 pub fn is_application(&self) -> bool {
1300 matches!(self, IntegrationOSError::Application(_))
1301 }
1302}
1303
1304impl ErrorMeta for IntegrationOSError {
1305 fn code(&self) -> ErrorCode {
1306 match self {
1307 IntegrationOSError::Internal(e) => e.code(),
1308 IntegrationOSError::Application(e) => e.code(),
1309 }
1310 }
1311
1312 fn key(&self) -> ErrorKey {
1313 match self {
1314 IntegrationOSError::Internal(e) => e.key(),
1315 IntegrationOSError::Application(e) => e.key(),
1316 }
1317 }
1318
1319 fn message(&self) -> ErrorMessage {
1320 match self {
1321 IntegrationOSError::Internal(e) => e.message(),
1322 IntegrationOSError::Application(e) => e.message(),
1323 }
1324 }
1325
1326 fn meta(&self) -> Option<Value> {
1327 match self {
1328 IntegrationOSError::Internal(e) => e.meta(),
1329 IntegrationOSError::Application(e) => e.meta(),
1330 }
1331 }
1332}
1333
1334impl Display for IntegrationOSError {
1335 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
1336 match self {
1337 IntegrationOSError::Internal(e) => write!(f, "{}", e),
1338 IntegrationOSError::Application(e) => write!(f, "{}", e),
1339 }
1340 }
1341}
1342
1343#[cfg(test)]
1344mod tests {
1345 use super::*;
1346
1347 #[test]
1348 fn test_new_function() {
1349 let internal_error: IntegrationOSError = InternalError::unknown("test", None);
1350
1351 assert_eq!(internal_error.code(), ErrorCode(1000),);
1352 assert_eq!(internal_error.key(), ErrorKey::internal("unknown", None),);
1353 assert_eq!(internal_error.message(), ErrorMessage("test".to_string()),);
1354 }
1355
1356 #[test]
1357 fn test_error_code() {
1358 let code = ErrorCode(400);
1359 assert_eq!(code.to_string(), "400");
1360 }
1361
1362 #[test]
1363 fn test_error_key() {
1364 let key = ErrorKey::internal("test", None);
1365 assert_eq!(key.to_string(), "err::internal::test");
1366 }
1367
1368 #[test]
1369 fn test_error_message() {
1370 let message = ErrorMessage("test".to_string());
1371 assert_eq!(message.to_string(), "test");
1372 }
1373
1374 #[test]
1375 fn test_interoperability_between_anyhow_error_and_domain_error() {
1376 let err = InternalError::unknown("test", None);
1377 let any_err: anyhow::Error = err.clone().into();
1378 let code: ErrorCode = any_err.downcast_ref::<IntegrationOSError>().unwrap().code();
1379 let message: ErrorMessage = any_err
1380 .downcast_ref::<IntegrationOSError>()
1381 .unwrap()
1382 .message();
1383 let key: ErrorKey = any_err.downcast_ref::<IntegrationOSError>().unwrap().key();
1384
1385 assert_eq!(code, ErrorCode(1000));
1386 assert_eq!(message, ErrorMessage("test".to_string()));
1387 assert_eq!(key, ErrorKey::internal("unknown", None));
1388 }
1389
1390 #[test]
1391 fn test_round_trip_between_domain_error_and_anyhow_error() {
1392 let err = InternalError::unknown("test", None);
1393 let any_err: anyhow::Error = err.clone().into();
1394 let round_trip_err = any_err.into();
1395
1396 let app_err = ApplicationError::bad_request("test", None);
1397 let any_app_err: anyhow::Error = app_err.clone().into();
1398 let round_trip_app_err = any_app_err.into();
1399
1400 assert_eq!(err, round_trip_err);
1401 assert_eq!(app_err, round_trip_app_err);
1402 }
1403
1404 #[test]
1405 fn from_internal_error_to_application_error() {
1406 let internal_error = InternalError::UniqueFieldViolation {
1407 message: "test".to_string(),
1408 subtype: None,
1409 meta: None,
1410 };
1411 let app_error: ApplicationError = internal_error.into();
1412
1413 assert_eq!(
1414 app_error,
1415 ApplicationError::Conflict {
1416 message: "test".to_string(),
1417 subtype: None,
1418 meta: None
1419 }
1420 );
1421 }
1422}