1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, ClientError>;
7
8#[derive(Error, Debug)]
10pub enum ClientError {
11 #[cfg(feature = "http-client")]
13 #[error("HTTP request failed: {0}")]
14 Http(#[from] reqwest::Error),
15
16 #[cfg(feature = "grpc")]
18 #[error("gRPC request failed: {0}")]
19 Grpc(String),
20
21 #[error("JSON error: {0}")]
23 Json(#[from] serde_json::Error),
24
25 #[error("Server error ({status}): {message}")]
27 Server {
28 status: u16,
30 message: String,
32 },
33
34 #[error("Invalid configuration: {0}")]
36 Config(String),
37
38 #[error("Namespace not found: {0}")]
40 NamespaceNotFound(String),
41
42 #[error("Vector not found: {0}")]
44 VectorNotFound(String),
45
46 #[error("Invalid URL: {0}")]
48 InvalidUrl(String),
49
50 #[error("Connection failed: {0}")]
52 Connection(String),
53
54 #[error("Request timeout")]
56 Timeout,
57}
58
59impl ClientError {
60 pub fn is_retryable(&self) -> bool {
62 match self {
63 #[cfg(feature = "http-client")]
64 ClientError::Http(e) => e.is_timeout() || e.is_connect(),
65 #[cfg(feature = "grpc")]
66 ClientError::Grpc(_) => true, ClientError::Server { status, .. } => *status >= 500,
68 ClientError::Connection(_) => true,
69 ClientError::Timeout => true,
70 _ => false,
71 }
72 }
73
74 pub fn is_not_found(&self) -> bool {
76 match self {
77 ClientError::Server { status, .. } => *status == 404,
78 ClientError::NamespaceNotFound(_) => true,
79 ClientError::VectorNotFound(_) => true,
80 _ => false,
81 }
82 }
83}