Skip to main content

haagenti_network/
error.rs

1//! Error types for network operations
2
3use thiserror::Error;
4
5/// Result type for network operations
6pub type Result<T> = std::result::Result<T, NetworkError>;
7
8/// Errors that can occur during network operations
9#[derive(Error, Debug)]
10pub enum NetworkError {
11    /// HTTP request failed
12    #[error("HTTP error: {status} - {message}")]
13    Http { status: u16, message: String },
14
15    /// Network connection failed
16    #[error("Connection failed: {0}")]
17    Connection(String),
18
19    /// Request timeout
20    #[error("Request timeout after {0}ms")]
21    Timeout(u64),
22
23    /// Invalid URL
24    #[error("Invalid URL: {0}")]
25    InvalidUrl(String),
26
27    /// Fragment not found on CDN
28    #[error("Fragment not found: {0}")]
29    NotFound(String),
30
31    /// Checksum mismatch
32    #[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    /// Cache error
40    #[error("Cache error: {0}")]
41    Cache(String),
42
43    /// All retries exhausted
44    #[error("All retries exhausted: {0}")]
45    RetriesExhausted(String),
46
47    /// Rate limited
48    #[error("Rate limited, retry after {retry_after_ms}ms")]
49    RateLimited { retry_after_ms: u64 },
50
51    /// CDN configuration error
52    #[error("CDN configuration error: {0}")]
53    Configuration(String),
54
55    /// IO error
56    #[error("IO error: {0}")]
57    Io(#[from] std::io::Error),
58
59    /// Cancelled
60    #[error("Request cancelled")]
61    Cancelled,
62}
63
64impl NetworkError {
65    /// Check if error is retryable
66    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    /// Get retry delay if rate limited
77    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}