xmtp_api_d14n/middleware/multi_node_client/
errors.rs

1use thiserror::Error;
2use xmtp_api_grpc::error::GrpcError;
3use xmtp_common::{MaybeSend, MaybeSync, RetryableError};
4use xmtp_proto::api::{ApiClientError, BodyError};
5
6/// Errors that can occur during multi-node client operations.
7#[derive(Debug, Error)]
8pub enum MultiNodeClientError {
9    #[error("all node clients failed to build")]
10    AllNodeClientsFailedToBuild,
11    #[error(transparent)]
12    BodyError(#[from] BodyError),
13    #[error(transparent)]
14    GrpcError(#[from] ApiClientError<GrpcError>),
15    #[error("node {} timed out under {}ms latency", node_id, latency)]
16    NodeTimedOut { node_id: u32, latency: u64 },
17    #[error("no nodes found")]
18    NoNodesFound,
19    #[error("no responsive nodes found under {latency}ms latency")]
20    NoResponsiveNodesFound { latency: u64 },
21    #[error("client builder tls channel does not match url tls channel")]
22    TlsChannelMismatch {
23        url_is_tls: bool,
24        client_builder_tls_channel: bool,
25    },
26    #[error("unhealthy node {}", node_id)]
27    UnhealthyNode { node_id: u32 },
28}
29
30/// From<MultiNodeClientError> for ApiClientError<E> is used to convert the MultiNodeClientError to an ApiClientError.
31/// Required by the Client trait implementation, as request and stream can return MultiNodeClientError.
32impl<E> From<MultiNodeClientError> for ApiClientError<E>
33where
34    E: std::error::Error + MaybeSend + MaybeSync + 'static,
35{
36    fn from(value: MultiNodeClientError) -> ApiClientError<E> {
37        ApiClientError::<E>::Other(Box::new(value))
38    }
39}
40
41/// Implements RetryableError to enable proper retry behavior in the API client error handling system.
42impl RetryableError for MultiNodeClientError {
43    fn is_retryable(&self) -> bool {
44        match self {
45            Self::GrpcError(e) => e.is_retryable(),
46            Self::BodyError(e) => e.is_retryable(),
47            _ => false,
48        }
49    }
50}