d_engine/client/builder.rs
1use std::sync::Arc;
2use std::time::Duration;
3
4use arc_swap::ArcSwap;
5
6use super::Client;
7use super::ClientApiError;
8use super::ClientConfig;
9use super::ClientInner;
10use super::ClusterClient;
11use super::ConnectionPool;
12use super::KvClient;
13
14/// Configurable builder for [`Client`] instances
15///
16/// Implements the **builder pattern** for constructing clients with
17/// customized connection parameters and timeouts.
18///
19/// # Typical Usage Flow
20/// 1. Create with `ClientBuilder::new()`
21/// 2. Chain configuration methods
22/// 3. Finalize with `.build()`
23///
24/// # Default Configuration
25/// - Compression: Enabled
26/// - Connect Timeout: 1s
27/// - Request Timeout: 3s
28pub struct ClientBuilder {
29 config: ClientConfig,
30 endpoints: Vec<String>,
31}
32
33impl ClientBuilder {
34 /// Create a new builder with default config and specified endpoints
35 pub fn new(endpoints: Vec<String>) -> Self {
36 Self {
37 config: ClientConfig::default(),
38 endpoints,
39 }
40 }
41
42 /// Set connection timeout (default: 1s)
43 pub fn connect_timeout(
44 mut self,
45 timeout: Duration,
46 ) -> Self {
47 self.config.connect_timeout = timeout;
48 self
49 }
50
51 /// Set request timeout (default: 3s)
52 pub fn request_timeout(
53 mut self,
54 timeout: Duration,
55 ) -> Self {
56 self.config.request_timeout = timeout;
57 self
58 }
59
60 /// Enable/disable compression (default: enabled)
61 pub fn enable_compression(
62 mut self,
63 enable: bool,
64 ) -> Self {
65 self.config.enable_compression = enable;
66 self
67 }
68
69 /// Completely replaces the default configuration
70 ///
71 /// # Warning: Configuration Override
72 /// This will discard all previous settings configured through individual
73 /// methods like [`connect_timeout`](ClientBuilder::connect_timeout) or
74 /// [`enable_compression`](ClientBuilder::enable_compression).
75 ///
76 /// # Usage Guidance
77 /// Choose **either**:
78 /// - Use granular configuration methods (recommended for most cases)
79 /// - Use this method to provide a full configuration object
80 ///
81 /// # Example: Full Configuration
82 /// ```no_run
83 /// use d_engine::client::{ClientBuilder, ClientConfig};
84 /// use std::time::Duration;
85 ///
86 /// let custom_config = ClientConfig {
87 /// connect_timeout: Duration::from_secs(2),
88 /// request_timeout: Duration::from_secs(5),
89 /// ..ClientConfig::default()
90 /// };
91 ///
92 /// let builder = ClientBuilder::new(vec!["http://node1:9081".into()])
93 /// .set_config(custom_config);
94 /// ```
95 pub fn set_config(
96 mut self,
97 config: ClientConfig,
98 ) -> Self {
99 self.config = config;
100 self
101 }
102
103 /// Build the client with current configuration
104 pub async fn build(self) -> std::result::Result<Client, ClientApiError> {
105 let pool = ConnectionPool::create(self.endpoints.clone(), self.config.clone()).await?;
106 let inner = Arc::new(ArcSwap::from_pointee(ClientInner {
107 pool,
108 client_id: self.config.id,
109 config: self.config,
110 endpoints: self.endpoints,
111 }));
112
113 Ok(Client {
114 kv: KvClient::new(inner.clone()),
115 cluster: ClusterClient::new(inner.clone()),
116 inner,
117 })
118 }
119}