orion_error/core/
universal.rs

1use serde::Serialize;
2use std::fmt::Display;
3use thiserror::Error;
4
5use super::ErrorCode;
6
7/// Configuration error sub-classification
8/// 配置错误子分类
9#[derive(Debug, Error, PartialEq, Clone, Serialize)]
10pub enum ConfErrReason {
11    #[error("core config > {0}")]
12    Core(String),
13    #[error("feature config error > {0}")]
14    Feature(String),
15    #[error("dynamic config error > {0}")]
16    Dynamic(String),
17}
18
19/// Universal error reason classification with clear hierarchical structure
20/// 统一错误原因分类 - 采用清晰的分层结构
21///
22/// # Error Code Ranges
23/// - 100-199: Business Layer Errors (业务层错误)
24/// - 200-299: Infrastructure Layer Errors (基础设施层错误)
25/// - 300-399: Configuration & External Layer Errors (配置和外部层错误)
26///
27/// # Classification Principles
28/// - Business Layer: User-facing errors that are expected in normal operation
29/// - Infrastructure Layer: System-level failures that should be rare
30/// - Configuration & External: Environment and third-party service issues
31#[derive(Debug, Error, PartialEq, Clone, Serialize)]
32pub enum UvsReason {
33    // === Business Layer Errors (100-199) ===
34    /// Input validation errors (格式错误、参数校验失败等)
35    #[error("validation error << {0}")]
36    ValidationError(ErrorPayload),
37
38    /// Business logic rule violations (业务规则违反、状态冲突等)
39    #[error("business logic error << {0}")]
40    BusinessError(ErrorPayload),
41
42    /// Resource not found (查询的资源不存在)
43    #[error("not found error << {0}")]
44    NotFoundError(ErrorPayload),
45
46    /// Permission and authorization errors (权限不足、认证失败)
47    #[error("permission error << {0}")]
48    PermissionError(ErrorPayload),
49
50    // === Infrastructure Layer Errors (200-299) ===
51    /// Database and data processing errors (数据库操作、数据格式错误)
52    #[error("data error << {0}")]
53    DataError(ErrorPayload, Option<usize>),
54
55    /// File system and OS-level errors (文件系统、操作系统错误)
56    #[error("system error << {0}")]
57    SystemError(ErrorPayload),
58
59    /// Network connectivity and protocol errors (网络连接、HTTP请求错误)
60    #[error("network error << {0}")]
61    NetworkError(ErrorPayload),
62
63    /// Resource exhaustion (内存不足、磁盘空间不足等)
64    #[error("resource error << {0}")]
65    ResourceError(ErrorPayload),
66
67    /// Operation timeouts (操作超时)
68    #[error("timeout error << {0}")]
69    TimeoutError(ErrorPayload),
70
71    // === Configuration & External Layer Errors (300-399) ===
72    /// Configuration-related errors (配置相关错误)
73    #[error("configuration error << {0}")]
74    ConfigError(ConfErrReason),
75
76    /// Third-party service errors (第三方服务错误)
77    #[error("external service error << {0}")]
78    ExternalError(ErrorPayload),
79
80    /// Third-party service errors (第三方服务错误)
81    #[error("BUG :logic error << {0}")]
82    LogicError(ErrorPayload),
83}
84
85impl UvsReason {
86    // === Configuration Error Constructors ===
87    pub fn core_conf<S: Into<String>>(msg: S) -> Self {
88        Self::ConfigError(ConfErrReason::Core(msg.into()))
89    }
90
91    pub fn feature_conf<S: Into<String>>(msg: S) -> Self {
92        Self::ConfigError(ConfErrReason::Feature(msg.into()))
93    }
94
95    pub fn dynamic_conf<S: Into<String>>(msg: S) -> Self {
96        Self::ConfigError(ConfErrReason::Dynamic(msg.into()))
97    }
98
99    // === Business Layer Constructors ===
100    pub fn validation_error<S: Into<String>>(msg: S) -> Self {
101        Self::ValidationError(ErrorPayload::new(msg))
102    }
103
104    pub fn business_error<S: Into<String>>(msg: S) -> Self {
105        Self::BusinessError(ErrorPayload::new(msg))
106    }
107
108    pub fn not_found_error<S: Into<String>>(msg: S) -> Self {
109        Self::NotFoundError(ErrorPayload::new(msg))
110    }
111
112    pub fn permission_error<S: Into<String>>(msg: S) -> Self {
113        Self::PermissionError(ErrorPayload::new(msg))
114    }
115
116    // === Infrastructure Layer Constructors ===
117    pub fn data_error<S: Into<String>>(msg: S, pos: Option<usize>) -> Self {
118        Self::DataError(ErrorPayload::new(msg), pos)
119    }
120
121    pub fn system_error<S: Into<String>>(msg: S) -> Self {
122        Self::SystemError(ErrorPayload::new(msg))
123    }
124
125    pub fn network_error<S: Into<String>>(msg: S) -> Self {
126        Self::NetworkError(ErrorPayload::new(msg))
127    }
128
129    pub fn resource_error<S: Into<String>>(msg: S) -> Self {
130        Self::ResourceError(ErrorPayload::new(msg))
131    }
132
133    pub fn timeout_error<S: Into<String>>(msg: S) -> Self {
134        Self::TimeoutError(ErrorPayload::new(msg))
135    }
136
137    // === External Layer Constructors ===
138    pub fn external_error<S: Into<String>>(msg: S) -> Self {
139        Self::ExternalError(ErrorPayload::new(msg))
140    }
141    pub fn logic_error<S: Into<String>>(msg: S) -> Self {
142        Self::LogicError(ErrorPayload::new(msg))
143    }
144}
145
146// === Trait Definitions for Type Conversion ===
147
148pub trait UvsConfFrom<S> {
149    fn from_conf(info: S) -> Self;
150}
151
152pub trait UvsDataFrom<S> {
153    fn from_data(info: S, pos: Option<usize>) -> Self;
154}
155
156pub trait UvsSysFrom<S> {
157    fn from_sys(info: S) -> Self;
158}
159
160pub trait UvsBizFrom<S> {
161    fn from_biz(info: S) -> Self;
162}
163pub trait UvsLogicFrom<S> {
164    fn from_logic(info: S) -> Self;
165}
166
167pub trait UvsResFrom<S> {
168    fn from_res(info: S) -> Self;
169}
170
171pub trait UvsNetFrom<S> {
172    fn from_net(info: S) -> Self;
173}
174
175pub trait UvsTimeoutFrom<S> {
176    fn from_timeout(info: S) -> Self;
177}
178
179// Additional traits for new error types
180pub trait UvsValidationFrom<S> {
181    fn from_validation(info: S) -> Self;
182}
183
184pub trait UvsNotFoundFrom<S> {
185    fn from_not_found(info: S) -> Self;
186}
187
188pub trait UvsPermissionFrom<S> {
189    fn from_permission(info: S) -> Self;
190}
191
192pub trait UvsExternalFrom<S> {
193    fn from_external(info: S) -> Self;
194}
195
196/// Strongly typed error payload wrapper
197/// 强类型错误负载包装
198#[derive(Debug, PartialEq, Clone, Serialize)]
199pub struct ErrorPayload(String);
200
201impl ErrorPayload {
202    pub fn new<S: Into<String>>(s: S) -> Self {
203        Self(s.into())
204    }
205
206    pub fn as_str(&self) -> &str {
207        &self.0
208    }
209
210    pub fn into_inner(self) -> String {
211        self.0
212    }
213}
214
215impl Display for ErrorPayload {
216    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217        write!(f, "{:?}", self.0)
218    }
219}
220
221impl From<String> for ErrorPayload {
222    fn from(value: String) -> Self {
223        Self::new(value)
224    }
225}
226
227impl From<&str> for ErrorPayload {
228    fn from(value: &str) -> Self {
229        Self::new(value.to_string())
230    }
231}
232
233// === Trait Implementations ===
234
235impl<T> UvsConfFrom<String> for T
236where
237    T: From<UvsReason>,
238{
239    fn from_conf(reason: String) -> Self {
240        T::from(UvsReason::core_conf(reason))
241    }
242}
243
244impl<T> UvsConfFrom<ConfErrReason> for T
245where
246    T: From<UvsReason>,
247{
248    fn from_conf(reason: ConfErrReason) -> Self {
249        T::from(UvsReason::ConfigError(reason))
250    }
251}
252
253impl<T> UvsDataFrom<String> for T
254where
255    T: From<UvsReason>,
256{
257    fn from_data(info: String, pos: Option<usize>) -> Self {
258        T::from(UvsReason::data_error(info, pos))
259    }
260}
261
262impl<T> UvsSysFrom<String> for T
263where
264    T: From<UvsReason>,
265{
266    fn from_sys(info: String) -> Self {
267        T::from(UvsReason::system_error(info))
268    }
269}
270
271impl<T> UvsBizFrom<String> for T
272where
273    T: From<UvsReason>,
274{
275    fn from_biz(info: String) -> Self {
276        T::from(UvsReason::business_error(info))
277    }
278}
279
280impl<T> UvsResFrom<String> for T
281where
282    T: From<UvsReason>,
283{
284    fn from_res(info: String) -> Self {
285        T::from(UvsReason::resource_error(info))
286    }
287}
288
289impl<T> UvsNetFrom<String> for T
290where
291    T: From<UvsReason>,
292{
293    fn from_net(info: String) -> Self {
294        T::from(UvsReason::network_error(info)) // Fixed: was incorrectly mapping to BizError
295    }
296}
297
298impl<T> UvsTimeoutFrom<String> for T
299where
300    T: From<UvsReason>,
301{
302    fn from_timeout(info: String) -> Self {
303        T::from(UvsReason::timeout_error(info))
304    }
305}
306
307// New trait implementations for additional error types
308impl<T> UvsValidationFrom<String> for T
309where
310    T: From<UvsReason>,
311{
312    fn from_validation(info: String) -> Self {
313        T::from(UvsReason::validation_error(info))
314    }
315}
316
317impl<T> UvsNotFoundFrom<String> for T
318where
319    T: From<UvsReason>,
320{
321    fn from_not_found(info: String) -> Self {
322        T::from(UvsReason::not_found_error(info))
323    }
324}
325
326impl<T> UvsPermissionFrom<String> for T
327where
328    T: From<UvsReason>,
329{
330    fn from_permission(info: String) -> Self {
331        T::from(UvsReason::permission_error(info))
332    }
333}
334
335impl<T> UvsExternalFrom<String> for T
336where
337    T: From<UvsReason>,
338{
339    fn from_external(info: String) -> Self {
340        T::from(UvsReason::external_error(info))
341    }
342}
343
344impl<T> UvsLogicFrom<String> for T
345where
346    T: From<UvsReason>,
347{
348    fn from_logic(info: String) -> Self {
349        T::from(UvsReason::logic_error(info))
350    }
351}
352
353impl ErrorCode for UvsReason {
354    fn error_code(&self) -> i32 {
355        match self {
356            // === Business Layer Errors (100-199) ===
357            UvsReason::ValidationError(_) => 100,
358            UvsReason::BusinessError(_) => 101,
359            UvsReason::NotFoundError(_) => 102,
360            UvsReason::PermissionError(_) => 103,
361            UvsReason::LogicError(_) => 104,
362
363            // === Infrastructure Layer Errors (200-299) ===
364            UvsReason::DataError(_, _) => 200,
365            UvsReason::SystemError(_) => 201,
366            UvsReason::NetworkError(_) => 202,
367            UvsReason::ResourceError(_) => 203,
368            UvsReason::TimeoutError(_) => 204,
369
370            // === Configuration & External Layer Errors (300-399) ===
371            UvsReason::ConfigError(_) => 300,
372            UvsReason::ExternalError(_) => 301,
373        }
374    }
375}
376
377// === Helper Functions for Common Use Cases ===
378
379impl UvsReason {
380    /// Check if this error is retryable
381    /// 检查错误是否可重试
382    pub fn is_retryable(&self) -> bool {
383        match self {
384            // Infrastructure errors are often retryable
385            UvsReason::NetworkError(_) => true,
386            UvsReason::TimeoutError(_) => true,
387            UvsReason::ResourceError(_) => true,
388            UvsReason::SystemError(_) => true,
389            UvsReason::ExternalError(_) => true,
390
391            // Business logic errors are generally not retryable
392            UvsReason::ValidationError(_) => false,
393            UvsReason::BusinessError(_) => false,
394            UvsReason::NotFoundError(_) => false,
395            UvsReason::PermissionError(_) => false,
396
397            // Configuration errors require manual intervention
398            UvsReason::ConfigError(_) => false,
399            UvsReason::DataError(_, _) => false,
400            UvsReason::LogicError(_) => false,
401        }
402    }
403
404    /// Check if this error should be logged with high severity
405    /// 检查错误是否需要高优先级记录
406    pub fn is_high_severity(&self) -> bool {
407        match self {
408            // System and infrastructure issues are high severity
409            UvsReason::SystemError(_) => true,
410            UvsReason::ResourceError(_) => true,
411            UvsReason::ConfigError(_) => true,
412
413            // Others are normal business operations
414            _ => false,
415        }
416    }
417
418    /// Get error category name for monitoring and metrics
419    /// 获取错误类别名称用于监控和指标
420    pub fn category_name(&self) -> &'static str {
421        match self {
422            UvsReason::ValidationError(_) => "validation",
423            UvsReason::BusinessError(_) => "business",
424            UvsReason::NotFoundError(_) => "not_found",
425            UvsReason::PermissionError(_) => "permission",
426            UvsReason::DataError(_, _) => "data",
427            UvsReason::SystemError(_) => "system",
428            UvsReason::NetworkError(_) => "network",
429            UvsReason::ResourceError(_) => "resource",
430            UvsReason::TimeoutError(_) => "timeout",
431            UvsReason::ConfigError(_) => "config",
432            UvsReason::ExternalError(_) => "external",
433            UvsReason::LogicError(_) => "logic",
434        }
435    }
436}
437
438#[cfg(test)]
439mod tests {
440    use super::*;
441
442    #[test]
443    fn test_error_code_ranges() {
444        // Business layer (100-199)
445        assert_eq!(UvsReason::validation_error("test").error_code(), 100);
446        assert_eq!(UvsReason::business_error("test").error_code(), 101);
447        assert_eq!(UvsReason::not_found_error("test").error_code(), 102);
448        assert_eq!(UvsReason::permission_error("test").error_code(), 103);
449
450        // Infrastructure layer (200-299)
451        assert_eq!(UvsReason::data_error("test", None).error_code(), 200);
452        assert_eq!(UvsReason::system_error("test").error_code(), 201);
453        assert_eq!(UvsReason::network_error("test").error_code(), 202);
454        assert_eq!(UvsReason::resource_error("test").error_code(), 203);
455        assert_eq!(UvsReason::timeout_error("test").error_code(), 204);
456
457        // Configuration & external layer (300-399)
458        assert_eq!(UvsReason::core_conf("test").error_code(), 300);
459        assert_eq!(UvsReason::external_error("test").error_code(), 301);
460    }
461
462    #[test]
463    fn test_retryable_errors() {
464        assert!(UvsReason::network_error("timeout").is_retryable());
465        assert!(UvsReason::timeout_error("request timeout").is_retryable());
466        assert!(!UvsReason::validation_error("invalid input").is_retryable());
467        assert!(!UvsReason::business_error("insufficient funds").is_retryable());
468    }
469
470    #[test]
471    fn test_high_severity_errors() {
472        assert!(UvsReason::system_error("disk full").is_high_severity());
473        assert!(UvsReason::resource_error("out of memory").is_high_severity());
474        assert!(!UvsReason::validation_error("bad format").is_high_severity());
475        assert!(!UvsReason::NotFoundError("user not found".into()).is_high_severity());
476    }
477
478    #[test]
479    fn test_category_names() {
480        assert_eq!(UvsReason::network_error("test").category_name(), "network");
481        assert_eq!(
482            UvsReason::business_error("test").category_name(),
483            "business"
484        );
485        assert_eq!(UvsReason::core_conf("test").category_name(), "config");
486    }
487
488    #[test]
489    fn test_trait_implementations() {
490        // Test that trait implementations work correctly
491        let reason: UvsReason = UvsReason::from_net("network error".to_string());
492        assert_eq!(reason.error_code(), 202);
493
494        let reason: UvsReason = UvsReason::from_validation("validation error".to_string());
495        assert_eq!(reason.error_code(), 100);
496
497        let reason: UvsReason = UvsReason::from_external("external error".to_string());
498        assert_eq!(reason.error_code(), 301);
499    }
500}