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>;