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}
197
198impl Display for ErrorType {
199 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200 match self {
201 Self::Network => write!(f, "Network"),
202 Self::Authentication => write!(f, "Authentication"),
203 Self::Validation => write!(f, "Validation"),
204 Self::Api => write!(f, "Api"),
205 Self::Configuration => write!(f, "Configuration"),
206 Self::Serialization => write!(f, "Serialization"),
207 Self::Business => write!(f, "Business"),
208 Self::Timeout => write!(f, "Timeout"),
209 Self::RateLimit => write!(f, "RateLimit"),
210 Self::ServiceUnavailable => write!(f, "ServiceUnavailable"),
211 Self::Internal => write!(f, "Internal"),
212 }
213 }
214}
215
216impl From<ErrorCode> for ErrorType {
218 fn from(code: ErrorCode) -> Self {
219 match code {
220 ErrorCode::NetworkTimeout
221 | ErrorCode::NetworkConnectionFailed
222 | ErrorCode::DnsResolutionFailed
223 | ErrorCode::SslCertificateError
224 | ErrorCode::ConnectionRefused => ErrorType::Network,
225 ErrorCode::Unauthorized
226 | ErrorCode::AccessTokenInvalid
227 | ErrorCode::AppAccessTokenInvalid
228 | ErrorCode::TenantAccessTokenInvalid
229 | ErrorCode::AuthenticationFailed
230 | ErrorCode::TokenExpired
231 | ErrorCode::PermissionDenied
232 | ErrorCode::AccessDenied => ErrorType::Authentication,
233 ErrorCode::BadRequest
234 | ErrorCode::ValidationError
235 | ErrorCode::MissingRequiredParameter
236 | ErrorCode::InvalidParameterFormat
237 | ErrorCode::ParameterOutOfRange => ErrorType::Validation,
238 ErrorCode::NotFound
239 | ErrorCode::MethodNotAllowed
240 | ErrorCode::Conflict
241 | ErrorCode::Forbidden => ErrorType::Api,
242 ErrorCode::TooManyRequests | ErrorCode::RateLimitExceeded => ErrorType::RateLimit,
243 ErrorCode::GatewayTimeout => ErrorType::Timeout,
244 ErrorCode::ServiceUnavailable
245 | ErrorCode::BadGateway
246 | ErrorCode::CacheServiceUnavailable => ErrorType::ServiceUnavailable,
247 ErrorCode::ConfigurationError => ErrorType::Configuration,
248 ErrorCode::Success => ErrorType::Api,
249 _ => ErrorType::Internal,
250 }
251 }
252}
253
254pub trait ErrorContextTrait {
256 fn user_message(&self) -> Option<&str>;
258
259 fn request_id(&self) -> Option<&str>;
261
262 fn operation(&self) -> Option<&str>;
264
265 fn component(&self) -> Option<&str>;
267
268 fn timestamp(&self) -> Option<chrono::DateTime<chrono::Utc>>;
270
271 fn get_context(&self, key: &str) -> Option<&str>;
273
274 fn all_context(&self) -> &std::collections::HashMap<String, String>;
276
277 fn has_context(&self, key: &str) -> bool {
279 self.get_context(key).is_some()
280 }
281
282 fn is_empty(&self) -> bool {
284 self.user_message().is_none()
285 && self.request_id().is_none()
286 && self.operation().is_none()
287 && self.component().is_none()
288 && self.all_context().is_empty()
289 }
290}
291
292use super::context::ErrorContext;
294
295impl ErrorContextTrait for ErrorContext {
296 fn user_message(&self) -> Option<&str> {
297 ErrorContext::user_message(self)
298 }
299
300 fn request_id(&self) -> Option<&str> {
301 ErrorContext::request_id(self)
302 }
303
304 fn operation(&self) -> Option<&str> {
305 ErrorContext::operation(self)
306 }
307
308 fn component(&self) -> Option<&str> {
309 ErrorContext::component(self)
310 }
311
312 fn timestamp(&self) -> Option<chrono::DateTime<chrono::Utc>> {
313 ErrorContext::timestamp(self).map(|st| {
314 let duration = st.duration_since(std::time::UNIX_EPOCH).unwrap_or_default();
315 chrono::DateTime::from_timestamp(duration.as_secs() as i64, 0)
316 .unwrap_or_else(chrono::Utc::now)
317 })
318 }
319
320 fn get_context(&self, key: &str) -> Option<&str> {
321 ErrorContext::get_context(self, key)
322 }
323
324 fn all_context(&self) -> &std::collections::HashMap<String, String> {
325 ErrorContext::all_context(self)
326 }
327}
328
329pub trait ErrorBuilderTrait: Sized {
331 fn message(self, message: impl Into<String>) -> Self;
333
334 fn request_id(self, request_id: impl Into<String>) -> Self;
336
337 fn operation(self, operation: impl Into<String>) -> Self;
339
340 fn component(self, component: impl Into<String>) -> Self;
342
343 fn context(self, key: impl Into<String>, value: impl Into<String>) -> Self;
345
346 fn build(self) -> super::CoreError;
348}
349
350pub trait ErrorFormatTrait {
352 fn format_user_message(&self) -> String;
354
355 fn format_developer_message(&self) -> String;
357
358 fn format_log_message(&self) -> String;
360
361 fn format_json(&self) -> serde_json::Result<serde_json::Value>;
363}
364
365pub trait FullErrorTrait:
369 ErrorTrait + ErrorContextTrait + ErrorFormatTrait + Debug + Display + Clone + Send + Sync + 'static
370{
371}
372
373#[cfg(test)]
374mod tests {
375 use super::*;
376
377 #[test]
378 fn test_error_severity() {
379 assert!(ErrorSeverity::Info < ErrorSeverity::Warning);
380 assert!(ErrorSeverity::Warning < ErrorSeverity::Error);
381 assert!(ErrorSeverity::Error < ErrorSeverity::Critical);
382
383 assert!(ErrorSeverity::Critical.requires_immediate_action());
384 assert!(ErrorSeverity::Info.is_auto_recoverable());
385 }
386
387 #[test]
388 fn test_error_type_display() {
389 assert_eq!(ErrorType::Network.to_string(), "Network");
390 assert_eq!(ErrorType::Authentication.to_string(), "Authentication");
391 assert_eq!(ErrorType::Validation.to_string(), "Validation");
392 }
393
394 #[test]
395 fn test_error_severity_display() {
396 assert_eq!(ErrorSeverity::Info.to_string(), "信息");
397 assert_eq!(ErrorSeverity::Warning.to_string(), "警告");
398 assert_eq!(ErrorSeverity::Error.to_string(), "错误");
399 assert_eq!(ErrorSeverity::Critical.to_string(), "严重错误");
400 }
401}