llm_incident_manager/integrations/common/
errors.rs1use thiserror::Error;
2
3#[derive(Error, Debug)]
5pub enum IntegrationError {
6 #[error("Connection error: {0}")]
8 Connection(String),
9
10 #[error("Request failed: {0}")]
12 RequestFailed(String),
13
14 #[error("Invalid response: {0}")]
16 InvalidResponse(String),
17
18 #[error("Operation timed out after {timeout_secs} seconds")]
20 Timeout { timeout_secs: u64 },
21
22 #[error("Retry exhausted for {operation} after {attempts} attempts")]
24 RetryExhausted { operation: String, attempts: u32 },
25
26 #[error("Configuration error: {0}")]
28 Configuration(String),
29
30 #[error("Authentication error: {0}")]
32 Authentication(String),
33
34 #[error("Rate limit exceeded: {0}")]
36 RateLimit(String),
37
38 #[error("Network error: {0}")]
40 Network(String),
41
42 #[error("Serialization error: {0}")]
44 Serialization(String),
45
46 #[error("Internal error: {0}")]
48 Internal(String),
49}
50
51impl IntegrationError {
52 pub fn is_retryable(&self) -> bool {
54 matches!(
55 self,
56 IntegrationError::Connection(_)
57 | IntegrationError::Network(_)
58 | IntegrationError::Timeout { .. }
59 )
60 }
61}
62
63pub type IntegrationResult<T> = Result<T, IntegrationError>;
65
66impl From<tonic::Status> for IntegrationError {
68 fn from(status: tonic::Status) -> Self {
69 use tonic::Code;
70 match status.code() {
71 Code::Unauthenticated => {
72 IntegrationError::Authentication(status.message().to_string())
73 }
74 Code::Unavailable => IntegrationError::Connection(status.message().to_string()),
75 Code::DeadlineExceeded => IntegrationError::Timeout { timeout_secs: 0 },
76 Code::ResourceExhausted => IntegrationError::RateLimit(status.message().to_string()),
77 _ => IntegrationError::RequestFailed(status.message().to_string()),
78 }
79 }
80}
81
82impl From<IntegrationError> for crate::error::AppError {
84 fn from(err: IntegrationError) -> Self {
85 match err {
86 IntegrationError::Connection(msg) => crate::error::AppError::Network(msg),
87 IntegrationError::RequestFailed(msg) => crate::error::AppError::Integration {
88 integration_source: "LLM".to_string(),
89 message: msg,
90 },
91 IntegrationError::InvalidResponse(msg) => crate::error::AppError::Integration {
92 integration_source: "LLM".to_string(),
93 message: msg,
94 },
95 IntegrationError::Timeout { timeout_secs } => {
96 crate::error::AppError::Timeout(format!("Timeout after {} seconds", timeout_secs))
97 }
98 IntegrationError::RetryExhausted { operation, attempts } => {
99 crate::error::AppError::Integration {
100 integration_source: "LLM".to_string(),
101 message: format!("Retry exhausted for {} after {} attempts", operation, attempts),
102 }
103 }
104 IntegrationError::Configuration(msg) => crate::error::AppError::Configuration(msg),
105 IntegrationError::Authentication(msg) => crate::error::AppError::Authentication(msg),
106 IntegrationError::RateLimit(msg) => crate::error::AppError::Integration {
107 integration_source: "LLM".to_string(),
108 message: format!("Rate limit: {}", msg),
109 },
110 IntegrationError::Network(msg) => crate::error::AppError::Network(msg),
111 IntegrationError::Serialization(msg) => crate::error::AppError::Serialization(msg),
112 IntegrationError::Internal(msg) => crate::error::AppError::Internal(msg),
113 }
114 }
115}