orion_error/core/
universal.rs

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