-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patherror.rs
More file actions
174 lines (140 loc) · 4.59 KB
/
error.rs
File metadata and controls
174 lines (140 loc) · 4.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//! Error types for the Web Documentation Resolver CLI.
//!
//! Provides typed ResolverError variants with thiserror.
use thiserror::Error;
/// Main error type for the resolver
#[derive(Debug, Error)]
pub enum ResolverError {
/// Network-related errors
#[error("Network error: {0}")]
Network(String),
/// Rate limit exceeded
#[error("Rate limit exceeded: {0}")]
RateLimit(String),
/// Authentication/authorization errors
#[error("Authentication error: {0}")]
Auth(String),
/// Quota/credit exhaustion
#[error("Quota exhausted: {0}")]
Quota(String),
/// Resource not found (404)
#[error("Not found: {0}")]
NotFound(String),
/// Parse/format errors
#[error("Parse error: {0}")]
Parse(String),
/// Configuration errors
#[error("Configuration error: {0}")]
Config(String),
/// Cache errors
#[error("Cache error: {0}")]
Cache(String),
/// Provider-specific errors
#[error("Provider error: {0}")]
Provider(String),
/// Unknown/internal errors
#[error("Unknown error: {0}")]
Unknown(String),
}
// Semantic cache error conversion (feature-gated)
#[cfg(feature = "semantic-cache")]
impl From<chaotic_semantic_memory::MemoryError> for ResolverError {
fn from(err: chaotic_semantic_memory::MemoryError) -> Self {
ResolverError::Cache(err.to_string())
}
}
impl ResolverError {
/// Create a new error with context
pub fn with_context<E: std::fmt::Display>(error: E, context: &str) -> Self {
ResolverError::Unknown(format!("{}: {}", context, error))
}
/// Check if this is a rate limit error
pub fn is_rate_limit(&self) -> bool {
matches!(self, ResolverError::RateLimit(_))
}
/// Check if this is an auth error
pub fn is_auth(&self) -> bool {
matches!(self, ResolverError::Auth(_))
}
/// Check if this is a quota error
pub fn is_quota(&self) -> bool {
matches!(self, ResolverError::Quota(_))
}
/// Check if this is a not found error
pub fn is_not_found(&self) -> bool {
matches!(self, ResolverError::NotFound(_))
}
}
// Note: We don't define a Result type alias here to avoid conflicts
// Use std::result::Result<T, ResolverError> directly in provider code
/// Detect error type from error message
pub fn detect_error_type(error: &str) -> ResolverError {
let error_lower = error.to_lowercase();
if error_lower.contains("429")
|| error_lower.contains("rate limit")
|| error_lower.contains("too many requests")
{
return ResolverError::RateLimit(error.to_string());
}
if error_lower.contains("401")
|| error_lower.contains("403")
|| error_lower.contains("unauthorized")
|| error_lower.contains("forbidden")
|| error_lower.contains("invalid api key")
{
return ResolverError::Auth(error.to_string());
}
if error_lower.contains("402")
|| error_lower.contains("quota")
|| error_lower.contains("credits")
|| error_lower.contains("insufficient")
|| error_lower.contains("payment required")
{
return ResolverError::Quota(error.to_string());
}
if error_lower.contains("404") || error_lower.contains("not found") {
return ResolverError::NotFound(error.to_string());
}
if error_lower.contains("network")
|| error_lower.contains("connection")
|| error_lower.contains("timeout")
{
return ResolverError::Network(error.to_string());
}
ResolverError::Unknown(error.to_string())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_rate_limit_detection() {
let err = detect_error_type("429 rate limit exceeded");
assert!(err.is_rate_limit());
let err = detect_error_type("Too many requests");
assert!(err.is_rate_limit());
}
#[test]
fn test_auth_detection() {
let err = detect_error_type("401 unauthorized");
assert!(err.is_auth());
let err = detect_error_type("403 forbidden");
assert!(err.is_auth());
}
#[test]
fn test_quota_detection() {
let err = detect_error_type("402 payment required");
assert!(err.is_quota());
let err = detect_error_type("Insufficient credits");
assert!(err.is_quota());
}
#[test]
fn test_not_found_detection() {
let err = detect_error_type("404 not found");
assert!(err.is_not_found());
}
#[test]
fn test_network_detection() {
let err = detect_error_type("Network connection error");
assert!(matches!(err, ResolverError::Network(_)));
}
}