xmtp_api_d14n/middleware/multi_node_client/
builder.rs

1use crate::{MultiNodeClient, middleware::MiddlewareBuilder};
2use thiserror::Error;
3use tokio::sync::OnceCell;
4use xmtp_api_grpc::{ClientBuilder, GrpcClient, error::GrpcBuilderError};
5use xmtp_common::time::Duration;
6use xmtp_configuration::MULTI_NODE_TIMEOUT_MS;
7use xmtp_proto::api_client::ApiBuilder;
8
9/* MultiNodeClientBuilder struct and its associated errors */
10
11pub struct MultiNodeClientBuilder {
12    gateway_builder: Option<ClientBuilder>,
13    timeout: Duration,
14    node_client_template: ClientBuilder,
15}
16
17/// Errors that can occur when building a MultiNodeClient.
18#[derive(Debug, Error)]
19pub enum MultiNodeClientBuilderError {
20    #[error(transparent)]
21    GrpcBuilderError(#[from] GrpcBuilderError),
22    #[error("timeout must be greater than 0")]
23    InvalidTimeout,
24    #[error("gateway builder is required")]
25    MissingGatewayBuilder,
26}
27
28/* MultiNodeClientBuilder implementations */
29
30// Default implementation for MultiNodeClientBuilder.
31// Allows invoking MultiNodeClientBuilder::default() to create a new builder with default values.
32impl Default for MultiNodeClientBuilder {
33    fn default() -> Self {
34        Self {
35            gateway_builder: None,
36            timeout: Duration::from_millis(MULTI_NODE_TIMEOUT_MS),
37            node_client_template: GrpcClient::builder(),
38        }
39    }
40}
41
42// Implement the MiddlewareBuilder trait for MultiNodeClientBuilder.
43// This defines how to build a MultiNodeClient from a MultiNodeClientBuilder.
44impl MiddlewareBuilder for MultiNodeClientBuilder {
45    fn set_gateway_builder(&mut self, gateway_builder: ClientBuilder) -> Result<(), Self::Error> {
46        self.gateway_builder = Some(gateway_builder);
47        Ok(())
48    }
49
50    fn set_node_client_builder(&mut self, node_builder: ClientBuilder) -> Result<(), Self::Error> {
51        self.node_client_template = node_builder;
52        Ok(())
53    }
54
55    fn set_timeout(&mut self, timeout: Duration) -> Result<(), Self::Error> {
56        self.timeout = timeout;
57        Ok(())
58    }
59}
60
61// Implement the ApiBuilder trait for MultiNodeClientBuilder.
62// This allows the MultiNodeClientBuilder to be passed as parameter to the D14nClientBuilder.
63impl ApiBuilder for MultiNodeClientBuilder {
64    type Output = MultiNodeClient;
65    type Error = MultiNodeClientBuilderError;
66
67    fn build(self) -> Result<Self::Output, Self::Error> {
68        let gateway_builder = self
69            .gateway_builder
70            .ok_or(MultiNodeClientBuilderError::MissingGatewayBuilder)?;
71
72        if self.timeout.is_zero() {
73            return Err(MultiNodeClientBuilderError::InvalidTimeout);
74        }
75
76        let gateway_client = gateway_builder.build()?;
77
78        Ok(MultiNodeClient {
79            gateway_client,
80            inner: OnceCell::new(),
81            timeout: self.timeout,
82            node_client_template: self.node_client_template,
83        })
84    }
85}