Skip to main content

error_forge/
async_error.rs

1use std::backtrace::Backtrace;
2use std::error::Error as StdError;
3
4#[cfg(feature = "async")]
5use async_trait::async_trait;
6
7/// An async-compatible version of the ForgeError trait.
8///
9/// This trait extends the standard error capabilities with async support,
10/// allowing for async error handling in futures and async functions.
11///
12/// # Example
13///
14/// Requires the `async` cargo feature (which pulls in `async-trait`).
15/// The hidden `#[cfg(feature = "async")]` gate means this doctest is
16/// only compiled when the feature is enabled — when running
17/// `cargo test --all-features` it executes normally, and when the
18/// feature is off it is silently skipped.
19///
20/// ```
21/// # #[cfg(feature = "async")] {
22/// use error_forge::async_error::AsyncForgeError;
23/// use async_trait::async_trait;
24/// use std::error::Error as StdError;
25///
26/// #[derive(Debug)]
27/// struct MyAsyncError { message: String }
28///
29/// impl std::fmt::Display for MyAsyncError {
30///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31///         write!(f, "{}", self.message)
32///     }
33/// }
34///
35/// impl std::error::Error for MyAsyncError {}
36///
37/// #[async_trait]
38/// impl AsyncForgeError for MyAsyncError {
39///     fn kind(&self) -> &'static str { "AsyncExample" }
40///     fn caption(&self) -> &'static str { "Async Example Error" }
41///
42///     async fn async_handle(&self) -> Result<(), Box<dyn StdError + Send + Sync>> {
43///         Ok(())
44///     }
45/// }
46/// # }
47/// ```
48#[cfg(feature = "async")]
49#[async_trait]
50pub trait AsyncForgeError: StdError + Send + Sync + 'static {
51    /// Returns the kind of error, typically matching the enum variant
52    fn kind(&self) -> &'static str;
53
54    /// Returns a human-readable caption for the error
55    fn caption(&self) -> &'static str;
56
57    /// Returns true if the operation can be retried
58    fn is_retryable(&self) -> bool {
59        false
60    }
61
62    /// Returns true if the error is fatal and should terminate the program
63    fn is_fatal(&self) -> bool {
64        false
65    }
66
67    /// Returns an appropriate HTTP status code for the error
68    fn status_code(&self) -> u16 {
69        500
70    }
71
72    /// Returns an appropriate process exit code for the error
73    fn exit_code(&self) -> i32 {
74        1
75    }
76
77    /// Returns a user-facing message that can be shown to end users
78    fn user_message(&self) -> String {
79        self.to_string()
80    }
81
82    /// Returns a detailed technical message for developers/logs
83    fn dev_message(&self) -> String {
84        format!("[{}] {}", self.kind(), self)
85    }
86
87    /// Returns a backtrace if available
88    fn backtrace(&self) -> Option<&Backtrace> {
89        None
90    }
91
92    /// Async method to handle the error. This allows implementing custom
93    /// async error handling logic.
94    async fn async_handle(&self) -> Result<(), Box<dyn StdError + Send + Sync>>;
95
96    /// Registers the error with the central error registry
97    fn register(&self) {
98        crate::macros::call_error_hook(
99            self.caption(),
100            self.kind(),
101            self.is_fatal(),
102            self.is_retryable(),
103        );
104    }
105}
106
107/// Type alias for async error-forge results.
108#[cfg(feature = "async")]
109pub type AsyncResult<T, E> = std::result::Result<T, E>;