Skip to main content

openlark_core/error/
traits.rs

1//! 现代化错误处理特征系统
2//!
3//! 定义了符合Rust最佳实践的错误处理特征和接口
4
5use crate::error::ErrorCode;
6use serde::{Deserialize, Serialize};
7use std::fmt::{Debug, Display};
8use std::time::Duration;
9
10/// 核心错误特征
11///
12/// 所有错误类型都应该实现此特征,提供统一的错误处理接口
13pub trait ErrorTrait: std::error::Error + Send + Sync + 'static {
14    /// 获取错误严重程度
15    fn severity(&self) -> ErrorSeverity;
16
17    /// 判断是否可重试
18    fn is_retryable(&self) -> bool;
19
20    /// 获取建议的重试延迟
21    fn retry_delay(&self, attempt: u32) -> Option<Duration>;
22
23    /// 获取用户友好的错误消息
24    fn user_message(&self) -> Option<&str>;
25
26    /// 获取错误上下文信息
27    fn context(&self) -> &ErrorContext;
28
29    /// 判断错误类型
30    fn error_type(&self) -> ErrorType;
31
32    /// 获取错误代码(如果有)
33    fn error_code(&self) -> Option<&str> {
34        None
35    }
36
37    /// 判断是否为用户错误
38    fn is_user_error(&self) -> bool {
39        matches!(
40            self.error_type(),
41            ErrorType::Validation | ErrorType::Authentication
42        )
43    }
44
45    /// 判断是否为系统错误
46    fn is_system_error(&self) -> bool {
47        matches!(
48            self.error_type(),
49            ErrorType::Network | ErrorType::ServiceUnavailable | ErrorType::Internal
50        )
51    }
52
53    /// 判断是否为网络错误
54    fn is_network_error(&self) -> bool {
55        matches!(self.error_type(), ErrorType::Network)
56    }
57
58    /// 判断是否为认证错误
59    fn is_auth_error(&self) -> bool {
60        matches!(self.error_type(), ErrorType::Authentication)
61    }
62
63    /// 判断是否为验证错误
64    fn is_validation_error(&self) -> bool {
65        matches!(self.error_type(), ErrorType::Validation)
66    }
67
68    /// 判断是否为超时错误
69    fn is_timeout_error(&self) -> bool {
70        matches!(self.error_type(), ErrorType::Timeout)
71    }
72
73    /// 判断是否为限流错误
74    fn is_rate_limited(&self) -> bool {
75        matches!(self.error_type(), ErrorType::RateLimit)
76    }
77
78    /// 判断是否为配置错误
79    fn is_config_error(&self) -> bool {
80        matches!(self.error_type(), ErrorType::Configuration)
81    }
82
83    /// 判断是否为序列化错误
84    fn is_serialization_error(&self) -> bool {
85        matches!(self.error_type(), ErrorType::Serialization)
86    }
87
88    /// 判断是否为业务错误
89    fn is_business_error(&self) -> bool {
90        matches!(self.error_type(), ErrorType::Business)
91    }
92
93    /// 判断是否为API错误
94    fn is_api_error(&self) -> bool {
95        matches!(self.error_type(), ErrorType::Api)
96    }
97
98    /// 判断是否为服务不可用错误
99    fn is_service_unavailable_error(&self) -> bool {
100        matches!(self.error_type(), ErrorType::ServiceUnavailable)
101    }
102}
103
104/// 错误严重程度
105#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
106pub enum ErrorSeverity {
107    /// 信息级别 - 成功或提示信息
108    Info,
109    /// 警告级别 - 客户端错误或可恢复问题
110    Warning,
111    /// 错误级别 - 认证权限错误或业务逻辑错误
112    Error,
113    /// 严重错误级别 - 系统故障或不可恢复问题
114    Critical,
115}
116
117impl ErrorSeverity {
118    /// 获取严重程度的数值表示
119    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    /// 获取严重程度的描述
129    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    /// 从数值创建严重程度(兼容旧接口)
139    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    /// 判断是否需要立即处理
150    pub fn requires_immediate_action(&self) -> bool {
151        matches!(self, Self::Critical | Self::Error)
152    }
153
154    /// 判断是否需要用户干预
155    pub fn requires_user_intervention(&self) -> bool {
156        matches!(self, Self::Error | Self::Critical)
157    }
158
159    /// 判断是否可以自动恢复
160    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/// 错误类型分类
172#[derive(Debug, Clone, Copy, PartialEq, Eq)]
173pub enum ErrorType {
174    /// 网络相关错误
175    Network,
176    /// 认证相关错误
177    Authentication,
178    /// 验证相关错误
179    Validation,
180    /// API相关错误
181    Api,
182    /// 配置相关错误
183    Configuration,
184    /// 序列化相关错误
185    Serialization,
186    /// 业务逻辑错误
187    Business,
188    /// 超时错误
189    Timeout,
190    /// 限流错误
191    RateLimit,
192    /// 服务不可用错误
193    ServiceUnavailable,
194    /// 内部系统错误
195    Internal,
196    /// 响应体过大错误
197    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
219/// 从 ErrorCode 转换到 ErrorType
220impl 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
258/// 错误上下文特征
259pub trait ErrorContextTrait {
260    /// 获取用户友好消息
261    fn user_message(&self) -> Option<&str>;
262
263    /// 获取请求ID
264    fn request_id(&self) -> Option<&str>;
265
266    /// 获取操作名称
267    fn operation(&self) -> Option<&str>;
268
269    /// 获取组件名称
270    fn component(&self) -> Option<&str>;
271
272    /// 获取时间戳
273    fn timestamp(&self) -> Option<chrono::DateTime<chrono::Utc>>;
274
275    /// 获取上下文信息
276    fn get_context(&self, key: &str) -> Option<&str>;
277
278    /// 获取所有上下文信息
279    fn all_context(&self) -> &std::collections::HashMap<String, String>;
280
281    /// 检查是否有指定的上下文键
282    fn has_context(&self, key: &str) -> bool {
283        self.get_context(key).is_some()
284    }
285
286    /// 判断是否为空
287    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
296/// 使用导入的ErrorContext类型
297use 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
333/// 错误构建器特征
334pub trait ErrorBuilderTrait: Sized {
335    /// 设置用户消息
336    fn message(self, message: impl Into<String>) -> Self;
337
338    /// 设置请求ID
339    fn request_id(self, request_id: impl Into<String>) -> Self;
340
341    /// 设置操作名称
342    fn operation(self, operation: impl Into<String>) -> Self;
343
344    /// 设置组件名称
345    fn component(self, component: impl Into<String>) -> Self;
346
347    /// 添加上下文信息
348    fn context(self, key: impl Into<String>, value: impl Into<String>) -> Self;
349
350    /// 构建错误(V3)
351    fn build(self) -> super::CoreError;
352}
353
354/// 错误格式化特征
355pub trait ErrorFormatTrait {
356    /// 格式化为用户友好的消息
357    fn format_user_message(&self) -> String;
358
359    /// 格式化为开发者友好的消息
360    fn format_developer_message(&self) -> String;
361
362    /// 格式化为日志消息
363    fn format_log_message(&self) -> String;
364
365    /// 格式化为JSON
366    fn format_json(&self) -> serde_json::Result<serde_json::Value>;
367}
368
369/// 完整错误特征
370///
371/// 组合所有错误相关特征的超级特征
372pub 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}