1use crate::error::ErrorCode;
6use serde::{Deserialize, Serialize};
7use std::fmt::{Debug, Display};
8use std::time::Duration;
9
10pub trait ErrorTrait: std::error::Error + Send + Sync + 'static {
14 fn severity(&self) -> ErrorSeverity;
16
17 fn is_retryable(&self) -> bool;
19
20 fn retry_delay(&self, attempt: u32) -> Option<Duration>;
22
23 fn user_message(&self) -> Option<&str>;
25
26 fn context(&self) -> &ErrorContext;
28
29 fn error_type(&self) -> ErrorType;
31
32 fn error_code(&self) -> Option<&str> {
34 None
35 }
36
37 fn is_user_error(&self) -> bool {
39 matches!(
40 self.error_type(),
41 ErrorType::Validation | ErrorType::Authentication
42 )
43 }
44
45 fn is_system_error(&self) -> bool {
47 matches!(
48 self.error_type(),
49 ErrorType::Network | ErrorType::ServiceUnavailable | ErrorType::Internal
50 )
51 }
52
53 fn is_network_error(&self) -> bool {
55 matches!(self.error_type(), ErrorType::Network)
56 }
57
58 fn is_auth_error(&self) -> bool {
60 matches!(self.error_type(), ErrorType::Authentication)
61 }
62
63 fn is_validation_error(&self) -> bool {
65 matches!(self.error_type(), ErrorType::Validation)
66 }
67
68 fn is_timeout_error(&self) -> bool {
70 matches!(self.error_type(), ErrorType::Timeout)
71 }
72
73 fn is_rate_limited(&self) -> bool {
75 matches!(self.error_type(), ErrorType::RateLimit)
76 }
77
78 fn is_config_error(&self) -> bool {
80 matches!(self.error_type(), ErrorType::Configuration)
81 }
82
83 fn is_serialization_error(&self) -> bool {
85 matches!(self.error_type(), ErrorType::Serialization)
86 }
87
88 fn is_business_error(&self) -> bool {
90 matches!(self.error_type(), ErrorType::Business)
91 }
92
93 fn is_api_error(&self) -> bool {
95 matches!(self.error_type(), ErrorType::Api)
96 }
97
98 fn is_service_unavailable_error(&self) -> bool {
100 matches!(self.error_type(), ErrorType::ServiceUnavailable)
101 }
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
106pub enum ErrorSeverity {
107 Info,
109 Warning,
111 Error,
113 Critical,
115}
116
117impl ErrorSeverity {
118 pub fn as_level(&self) -> u8 {
120 match self {
121 Self::Info => 0,
122 Self::Warning => 1,
123 Self::Error => 2,
124 Self::Critical => 3,
125 }
126 }
127
128 pub fn description(&self) -> &'static str {
130 match self {
131 Self::Info => "信息",
132 Self::Warning => "警告",
133 Self::Error => "错误",
134 Self::Critical => "严重错误",
135 }
136 }
137
138 pub fn from_level(level: u8) -> Self {
140 match level {
141 0 => Self::Info,
142 1 => Self::Warning,
143 2 => Self::Error,
144 3 => Self::Critical,
145 _ => Self::Error,
146 }
147 }
148
149 pub fn requires_immediate_action(&self) -> bool {
151 matches!(self, Self::Critical | Self::Error)
152 }
153
154 pub fn requires_user_intervention(&self) -> bool {
156 matches!(self, Self::Error | Self::Critical)
157 }
158
159 pub fn is_auto_recoverable(&self) -> bool {
161 matches!(self, Self::Info | Self::Warning)
162 }
163}
164
165impl Display for ErrorSeverity {
166 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167 write!(f, "{}", self.description())
168 }
169}
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq)]
173pub enum ErrorType {
174 Network,
176 Authentication,
178 Validation,
180 Api,
182 Configuration,
184 Serialization,
186 Business,
188 Timeout,
190 RateLimit,
192 ServiceUnavailable,
194 Internal,
196 ResponseTooLarge,
198}
199
200impl Display for ErrorType {
201 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202 match self {
203 Self::Network => write!(f, "Network"),
204 Self::Authentication => write!(f, "Authentication"),
205 Self::Validation => write!(f, "Validation"),
206 Self::Api => write!(f, "Api"),
207 Self::Configuration => write!(f, "Configuration"),
208 Self::Serialization => write!(f, "Serialization"),
209 Self::Business => write!(f, "Business"),
210 Self::Timeout => write!(f, "Timeout"),
211 Self::RateLimit => write!(f, "RateLimit"),
212 Self::ServiceUnavailable => write!(f, "ServiceUnavailable"),
213 Self::Internal => write!(f, "Internal"),
214 Self::ResponseTooLarge => write!(f, "ResponseTooLarge"),
215 }
216 }
217}
218
219impl From<ErrorCode> for ErrorType {
221 fn from(code: ErrorCode) -> Self {
222 match code {
223 ErrorCode::NetworkTimeout
224 | ErrorCode::NetworkConnectionFailed
225 | ErrorCode::DnsResolutionFailed
226 | ErrorCode::SslCertificateError
227 | ErrorCode::ConnectionRefused => ErrorType::Network,
228 ErrorCode::Unauthorized
229 | ErrorCode::AccessTokenInvalid
230 | ErrorCode::AppAccessTokenInvalid
231 | ErrorCode::TenantAccessTokenInvalid
232 | ErrorCode::AuthenticationFailed
233 | ErrorCode::TokenExpired
234 | ErrorCode::PermissionDenied
235 | ErrorCode::AccessDenied => ErrorType::Authentication,
236 ErrorCode::BadRequest
237 | ErrorCode::ValidationError
238 | ErrorCode::MissingRequiredParameter
239 | ErrorCode::InvalidParameterFormat
240 | ErrorCode::ParameterOutOfRange => ErrorType::Validation,
241 ErrorCode::NotFound
242 | ErrorCode::MethodNotAllowed
243 | ErrorCode::Conflict
244 | ErrorCode::Forbidden => ErrorType::Api,
245 ErrorCode::TooManyRequests | ErrorCode::RateLimitExceeded => ErrorType::RateLimit,
246 ErrorCode::GatewayTimeout => ErrorType::Timeout,
247 ErrorCode::ServiceUnavailable
248 | ErrorCode::BadGateway
249 | ErrorCode::CacheServiceUnavailable => ErrorType::ServiceUnavailable,
250 ErrorCode::ConfigurationError => ErrorType::Configuration,
251 ErrorCode::ResponseTooLarge => ErrorType::ResponseTooLarge,
252 ErrorCode::Success => ErrorType::Api,
253 _ => ErrorType::Internal,
254 }
255 }
256}
257
258pub trait ErrorContextTrait {
260 fn user_message(&self) -> Option<&str>;
262
263 fn request_id(&self) -> Option<&str>;
265
266 fn operation(&self) -> Option<&str>;
268
269 fn component(&self) -> Option<&str>;
271
272 fn timestamp(&self) -> Option<chrono::DateTime<chrono::Utc>>;
274
275 fn get_context(&self, key: &str) -> Option<&str>;
277
278 fn all_context(&self) -> &std::collections::HashMap<String, String>;
280
281 fn has_context(&self, key: &str) -> bool {
283 self.get_context(key).is_some()
284 }
285
286 fn is_empty(&self) -> bool {
288 self.user_message().is_none()
289 && self.request_id().is_none()
290 && self.operation().is_none()
291 && self.component().is_none()
292 && self.all_context().is_empty()
293 }
294}
295
296use super::context::ErrorContext;
298
299impl ErrorContextTrait for ErrorContext {
300 fn user_message(&self) -> Option<&str> {
301 ErrorContext::user_message(self)
302 }
303
304 fn request_id(&self) -> Option<&str> {
305 ErrorContext::request_id(self)
306 }
307
308 fn operation(&self) -> Option<&str> {
309 ErrorContext::operation(self)
310 }
311
312 fn component(&self) -> Option<&str> {
313 ErrorContext::component(self)
314 }
315
316 fn timestamp(&self) -> Option<chrono::DateTime<chrono::Utc>> {
317 ErrorContext::timestamp(self).map(|st| {
318 let duration = st.duration_since(std::time::UNIX_EPOCH).unwrap_or_default();
319 chrono::DateTime::from_timestamp(duration.as_secs() as i64, 0)
320 .unwrap_or_else(chrono::Utc::now)
321 })
322 }
323
324 fn get_context(&self, key: &str) -> Option<&str> {
325 ErrorContext::get_context(self, key)
326 }
327
328 fn all_context(&self) -> &std::collections::HashMap<String, String> {
329 ErrorContext::all_context(self)
330 }
331}
332
333pub trait ErrorBuilderTrait: Sized {
335 fn message(self, message: impl Into<String>) -> Self;
337
338 fn request_id(self, request_id: impl Into<String>) -> Self;
340
341 fn operation(self, operation: impl Into<String>) -> Self;
343
344 fn component(self, component: impl Into<String>) -> Self;
346
347 fn context(self, key: impl Into<String>, value: impl Into<String>) -> Self;
349
350 fn build(self) -> super::CoreError;
352}
353
354pub trait ErrorFormatTrait {
356 fn format_user_message(&self) -> String;
358
359 fn format_developer_message(&self) -> String;
361
362 fn format_log_message(&self) -> String;
364
365 fn format_json(&self) -> serde_json::Result<serde_json::Value>;
367}
368
369pub trait FullErrorTrait:
373 ErrorTrait + ErrorContextTrait + ErrorFormatTrait + Debug + Display + Clone + Send + Sync + 'static
374{
375}
376
377#[cfg(test)]
378mod tests {
379 use super::*;
380
381 #[test]
382 fn test_error_severity() {
383 assert!(ErrorSeverity::Info < ErrorSeverity::Warning);
384 assert!(ErrorSeverity::Warning < ErrorSeverity::Error);
385 assert!(ErrorSeverity::Error < ErrorSeverity::Critical);
386
387 assert!(ErrorSeverity::Critical.requires_immediate_action());
388 assert!(ErrorSeverity::Info.is_auto_recoverable());
389 }
390
391 #[test]
392 fn test_error_type_display() {
393 assert_eq!(ErrorType::Network.to_string(), "Network");
394 assert_eq!(ErrorType::Authentication.to_string(), "Authentication");
395 assert_eq!(ErrorType::Validation.to_string(), "Validation");
396 }
397
398 #[test]
399 fn test_error_severity_display() {
400 assert_eq!(ErrorSeverity::Info.to_string(), "信息");
401 assert_eq!(ErrorSeverity::Warning.to_string(), "警告");
402 assert_eq!(ErrorSeverity::Error.to_string(), "错误");
403 assert_eq!(ErrorSeverity::Critical.to_string(), "严重错误");
404 }
405}