haagenti_network/
error.rs1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, NetworkError>;
7
8#[derive(Error, Debug)]
10pub enum NetworkError {
11 #[error("HTTP error: {status} - {message}")]
13 Http { status: u16, message: String },
14
15 #[error("Connection failed: {0}")]
17 Connection(String),
18
19 #[error("Request timeout after {0}ms")]
21 Timeout(u64),
22
23 #[error("Invalid URL: {0}")]
25 InvalidUrl(String),
26
27 #[error("Fragment not found: {0}")]
29 NotFound(String),
30
31 #[error("Checksum mismatch for {fragment_id}: expected {expected}, got {actual}")]
33 ChecksumMismatch {
34 fragment_id: String,
35 expected: String,
36 actual: String,
37 },
38
39 #[error("Cache error: {0}")]
41 Cache(String),
42
43 #[error("All retries exhausted: {0}")]
45 RetriesExhausted(String),
46
47 #[error("Rate limited, retry after {retry_after_ms}ms")]
49 RateLimited { retry_after_ms: u64 },
50
51 #[error("CDN configuration error: {0}")]
53 Configuration(String),
54
55 #[error("IO error: {0}")]
57 Io(#[from] std::io::Error),
58
59 #[error("Request cancelled")]
61 Cancelled,
62}
63
64impl NetworkError {
65 pub fn is_retryable(&self) -> bool {
67 match self {
68 NetworkError::Connection(_) => true,
69 NetworkError::Timeout(_) => true,
70 NetworkError::RateLimited { .. } => true,
71 NetworkError::Http { status, .. } => *status >= 500,
72 _ => false,
73 }
74 }
75
76 pub fn retry_after(&self) -> Option<std::time::Duration> {
78 if let NetworkError::RateLimited { retry_after_ms } = self {
79 Some(std::time::Duration::from_millis(*retry_after_ms))
80 } else {
81 None
82 }
83 }
84}
85
86impl From<reqwest::Error> for NetworkError {
87 fn from(e: reqwest::Error) -> Self {
88 if e.is_timeout() {
89 NetworkError::Timeout(30000)
90 } else if e.is_connect() {
91 NetworkError::Connection(e.to_string())
92 } else if let Some(status) = e.status() {
93 NetworkError::Http {
94 status: status.as_u16(),
95 message: e.to_string(),
96 }
97 } else {
98 NetworkError::Connection(e.to_string())
99 }
100 }
101}
102
103impl From<url::ParseError> for NetworkError {
104 fn from(e: url::ParseError) -> Self {
105 NetworkError::InvalidUrl(e.to_string())
106 }
107}