chie_shared/config/
timeout.rs

1//! Timeout configuration
2
3use serde::{Deserialize, Serialize};
4
5/// Timeout configuration for operations
6///
7/// # Examples
8///
9/// Using the default configuration:
10/// ```
11/// use chie_shared::TimeoutConfig;
12///
13/// let config = TimeoutConfig::default();
14/// assert_eq!(config.default_timeout_ms, 30_000);
15/// assert_eq!(config.connection_timeout_ms, 10_000);
16/// assert!(config.keepalive_enabled());
17/// assert!(config.idle_timeout_enabled());
18/// assert!(config.validate().is_ok());
19/// ```
20///
21/// Using preset configurations for different scenarios:
22/// ```
23/// use chie_shared::TimeoutConfig;
24///
25/// // Fast configuration for low-latency operations
26/// let fast_config = TimeoutConfig::fast();
27/// assert_eq!(fast_config.default_timeout_ms, 5_000);
28/// assert_eq!(fast_config.connection_timeout_ms, 3_000);
29///
30/// // Slow configuration for batch/background operations
31/// let slow_config = TimeoutConfig::slow();
32/// assert_eq!(slow_config.default_timeout_ms, 120_000);
33/// assert_eq!(slow_config.read_timeout_ms, 300_000);
34/// ```
35///
36/// Building a custom configuration:
37/// ```
38/// use chie_shared::TimeoutConfigBuilder;
39///
40/// let config = TimeoutConfigBuilder::new()
41///     .default_timeout_ms(45_000)
42///     .connection_timeout_ms(15_000)
43///     .read_timeout_ms(90_000)
44///     .write_timeout_ms(90_000)
45///     .idle_timeout_ms(0)  // Disable idle timeout
46///     .keepalive_interval_ms(30_000)
47///     .build();
48///
49/// assert_eq!(config.default_timeout_ms, 45_000);
50/// assert!(!config.idle_timeout_enabled());
51/// assert!(config.keepalive_enabled());
52/// ```
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct TimeoutConfig {
55    /// Default operation timeout in milliseconds
56    pub default_timeout_ms: u64,
57    /// Connection timeout in milliseconds
58    pub connection_timeout_ms: u64,
59    /// Read timeout in milliseconds
60    pub read_timeout_ms: u64,
61    /// Write timeout in milliseconds
62    pub write_timeout_ms: u64,
63    /// Idle timeout in milliseconds (0 = no timeout)
64    pub idle_timeout_ms: u64,
65    /// Keepalive interval in milliseconds (0 = disabled)
66    pub keepalive_interval_ms: u64,
67}
68
69impl Default for TimeoutConfig {
70    fn default() -> Self {
71        Self {
72            default_timeout_ms: 30_000,    // 30 seconds
73            connection_timeout_ms: 10_000, // 10 seconds
74            read_timeout_ms: 60_000,       // 60 seconds
75            write_timeout_ms: 60_000,      // 60 seconds
76            idle_timeout_ms: 300_000,      // 5 minutes
77            keepalive_interval_ms: 60_000, // 1 minute
78        }
79    }
80}
81
82impl TimeoutConfig {
83    /// Create a new configuration for fast operations
84    #[must_use]
85    pub const fn fast() -> Self {
86        Self {
87            default_timeout_ms: 5_000,
88            connection_timeout_ms: 3_000,
89            read_timeout_ms: 10_000,
90            write_timeout_ms: 10_000,
91            idle_timeout_ms: 60_000,
92            keepalive_interval_ms: 30_000,
93        }
94    }
95
96    /// Create a new configuration for slow operations
97    #[must_use]
98    pub const fn slow() -> Self {
99        Self {
100            default_timeout_ms: 120_000,
101            connection_timeout_ms: 30_000,
102            read_timeout_ms: 300_000,
103            write_timeout_ms: 300_000,
104            idle_timeout_ms: 600_000,
105            keepalive_interval_ms: 120_000,
106        }
107    }
108
109    /// Check if keepalive is enabled
110    #[must_use]
111    pub const fn keepalive_enabled(&self) -> bool {
112        self.keepalive_interval_ms > 0
113    }
114
115    /// Check if idle timeout is enabled
116    #[must_use]
117    pub const fn idle_timeout_enabled(&self) -> bool {
118        self.idle_timeout_ms > 0
119    }
120
121    /// Validate the timeout configuration
122    ///
123    /// # Errors
124    ///
125    /// Returns error if configuration is invalid
126    pub fn validate(&self) -> crate::ChieResult<()> {
127        use crate::ChieError;
128
129        if self.default_timeout_ms == 0 {
130            return Err(ChieError::validation(
131                "default_timeout_ms must be greater than 0",
132            ));
133        }
134
135        if self.connection_timeout_ms == 0 {
136            return Err(ChieError::validation(
137                "connection_timeout_ms must be greater than 0",
138            ));
139        }
140
141        if self.read_timeout_ms == 0 {
142            return Err(ChieError::validation(
143                "read_timeout_ms must be greater than 0",
144            ));
145        }
146
147        if self.write_timeout_ms == 0 {
148            return Err(ChieError::validation(
149                "write_timeout_ms must be greater than 0",
150            ));
151        }
152
153        Ok(())
154    }
155}
156
157/// Builder for `TimeoutConfig`
158///
159/// # Examples
160///
161/// Building a configuration for API requests:
162/// ```
163/// use chie_shared::TimeoutConfigBuilder;
164///
165/// let config = TimeoutConfigBuilder::new()
166///     .default_timeout_ms(20_000)
167///     .connection_timeout_ms(5_000)
168///     .read_timeout_ms(30_000)
169///     .write_timeout_ms(30_000)
170///     .keepalive_interval_ms(45_000)
171///     .build();
172///
173/// assert_eq!(config.default_timeout_ms, 20_000);
174/// assert!(config.validate().is_ok());
175/// ```
176#[derive(Debug, Default)]
177pub struct TimeoutConfigBuilder {
178    config: TimeoutConfig,
179}
180
181impl TimeoutConfigBuilder {
182    /// Create a new builder with default values
183    #[must_use]
184    pub fn new() -> Self {
185        Self::default()
186    }
187
188    /// Set default timeout
189    #[must_use]
190    pub const fn default_timeout_ms(mut self, ms: u64) -> Self {
191        self.config.default_timeout_ms = ms;
192        self
193    }
194
195    /// Set connection timeout
196    #[must_use]
197    pub const fn connection_timeout_ms(mut self, ms: u64) -> Self {
198        self.config.connection_timeout_ms = ms;
199        self
200    }
201
202    /// Set read timeout
203    #[must_use]
204    pub const fn read_timeout_ms(mut self, ms: u64) -> Self {
205        self.config.read_timeout_ms = ms;
206        self
207    }
208
209    /// Set write timeout
210    #[must_use]
211    pub const fn write_timeout_ms(mut self, ms: u64) -> Self {
212        self.config.write_timeout_ms = ms;
213        self
214    }
215
216    /// Set idle timeout
217    #[must_use]
218    pub const fn idle_timeout_ms(mut self, ms: u64) -> Self {
219        self.config.idle_timeout_ms = ms;
220        self
221    }
222
223    /// Set keepalive interval
224    #[must_use]
225    pub const fn keepalive_interval_ms(mut self, ms: u64) -> Self {
226        self.config.keepalive_interval_ms = ms;
227        self
228    }
229
230    /// Build the configuration
231    #[must_use]
232    pub const fn build(self) -> TimeoutConfig {
233        self.config
234    }
235}