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
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
216/// 从 ErrorCode 转换到 ErrorType
217impl 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
254/// 错误上下文特征
255pub trait ErrorContextTrait {
256    /// 获取用户友好消息
257    fn user_message(&self) -> Option<&str>;
258
259    /// 获取请求ID
260    fn request_id(&self) -> Option<&str>;
261
262    /// 获取操作名称
263    fn operation(&self) -> Option<&str>;
264
265    /// 获取组件名称
266    fn component(&self) -> Option<&str>;
267
268    /// 获取时间戳
269    fn timestamp(&self) -> Option<chrono::DateTime<chrono::Utc>>;
270
271    /// 获取上下文信息
272    fn get_context(&self, key: &str) -> Option<&str>;
273
274    /// 获取所有上下文信息
275    fn all_context(&self) -> &std::collections::HashMap<String, String>;
276
277    /// 检查是否有指定的上下文键
278    fn has_context(&self, key: &str) -> bool {
279        self.get_context(key).is_some()
280    }
281
282    /// 判断是否为空
283    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
292/// 使用导入的ErrorContext类型
293use 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
329/// 错误构建器特征
330pub trait ErrorBuilderTrait: Sized {
331    /// 设置用户消息
332    fn message(self, message: impl Into<String>) -> Self;
333
334    /// 设置请求ID
335    fn request_id(self, request_id: impl Into<String>) -> Self;
336
337    /// 设置操作名称
338    fn operation(self, operation: impl Into<String>) -> Self;
339
340    /// 设置组件名称
341    fn component(self, component: impl Into<String>) -> Self;
342
343    /// 添加上下文信息
344    fn context(self, key: impl Into<String>, value: impl Into<String>) -> Self;
345
346    /// 构建错误(V3)
347    fn build(self) -> super::CoreError;
348}
349
350/// 错误格式化特征
351pub trait ErrorFormatTrait {
352    /// 格式化为用户友好的消息
353    fn format_user_message(&self) -> String;
354
355    /// 格式化为开发者友好的消息
356    fn format_developer_message(&self) -> String;
357
358    /// 格式化为日志消息
359    fn format_log_message(&self) -> String;
360
361    /// 格式化为JSON
362    fn format_json(&self) -> serde_json::Result<serde_json::Value>;
363}
364
365/// 完整错误特征
366///
367/// 组合所有错误相关特征的超级特征
368pub 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}