CommonLibrary/Transport/
TransportConfig.rs1use std::{collections::HashMap, time::Duration};
6
7use serde::{Deserialize, Serialize};
8
9use super::Common::TransportType;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct TransportConfig {
14 pub DefaultTimeout:Duration,
16
17 pub MaximumRetries:u32,
19
20 pub RetryBaseDelay:Duration,
22
23 pub RetryMaximumDelay:Duration,
25
26 pub RetryJitterEnabled:bool,
29
30 pub CircuitBreakerFailureThreshold:u32,
33
34 pub CircuitBreakerResetTimeout:Duration,
36
37 pub HealthChecksEnabled:bool,
39
40 pub HealthCheckInterval:Duration,
42
43 pub MetricsEnabled:bool,
45
46 #[serde(skip_serializing_if = "HashMap::is_empty")]
48 pub TransportConfigurations:HashMap<TransportType, serde_json::Value>,
49
50 #[serde(skip_serializing_if = "Vec::is_empty")]
52 pub AllowedTransports:Vec<TransportType>,
53
54 #[serde(skip_serializing_if = "Vec::is_empty")]
56 pub ForbiddenTransports:Vec<TransportType>,
57}
58
59impl Default for TransportConfig {
60 fn default() -> Self {
61 Self {
62 DefaultTimeout:Duration::from_secs(30),
63
64 MaximumRetries:3,
65
66 RetryBaseDelay:Duration::from_millis(100),
67
68 RetryMaximumDelay:Duration::from_secs(10),
69
70 RetryJitterEnabled:true,
71
72 CircuitBreakerFailureThreshold:5,
73
74 CircuitBreakerResetTimeout:Duration::from_secs(60),
75
76 HealthChecksEnabled:true,
77
78 HealthCheckInterval:Duration::from_secs(30),
79
80 MetricsEnabled:true,
81
82 TransportConfigurations:HashMap::new(),
83
84 AllowedTransports:Vec::new(),
85
86 ForbiddenTransports:Vec::new(),
87 }
88 }
89}
90
91impl TransportConfig {
92 pub fn New() -> Self { Self::default() }
94
95 pub fn WithDefaultTimeout(mut self, Timeout:Duration) -> Self {
97 self.DefaultTimeout = Timeout;
98
99 self
100 }
101
102 pub fn WithMaximumRetries(mut self, MaximumRetries:u32) -> Self {
104 self.MaximumRetries = MaximumRetries;
105
106 self
107 }
108
109 pub fn WithRetryBaseDelay(mut self, Delay:Duration) -> Self {
111 self.RetryBaseDelay = Delay;
112
113 self
114 }
115
116 pub fn WithRetryMaximumDelay(mut self, Delay:Duration) -> Self {
118 self.RetryMaximumDelay = Delay;
119
120 self
121 }
122
123 pub fn WithRetryJitter(mut self, Enabled:bool) -> Self {
125 self.RetryJitterEnabled = Enabled;
126
127 self
128 }
129
130 pub fn WithCircuitBreakerThreshold(mut self, Threshold:u32) -> Self {
132 self.CircuitBreakerFailureThreshold = Threshold;
133
134 self
135 }
136
137 pub fn WithCircuitBreakerResetTimeout(mut self, Timeout:Duration) -> Self {
139 self.CircuitBreakerResetTimeout = Timeout;
140
141 self
142 }
143
144 pub fn WithHealthChecksEnabled(mut self, Enabled:bool) -> Self {
146 self.HealthChecksEnabled = Enabled;
147
148 self
149 }
150
151 pub fn WithHealthCheckInterval(mut self, Interval:Duration) -> Self {
153 self.HealthCheckInterval = Interval;
154
155 self
156 }
157
158 pub fn WithMetricsEnabled(mut self, Enabled:bool) -> Self {
160 self.MetricsEnabled = Enabled;
161
162 self
163 }
164
165 pub fn WithTransportConfiguration(mut self, TransportKind:TransportType, Configuration:serde_json::Value) -> Self {
167 self.TransportConfigurations.insert(TransportKind, Configuration);
168
169 self
170 }
171
172 pub fn GetTransportConfiguration(&self, TransportKind:TransportType) -> Option<&serde_json::Value> {
174 self.TransportConfigurations.get(&TransportKind)
175 }
176
177 pub fn WithAllowedTransports(mut self, Transports:Vec<TransportType>) -> Self {
179 self.AllowedTransports = Transports;
180
181 self
182 }
183
184 pub fn AddForbiddenTransport(mut self, TransportKind:TransportType) -> Self {
186 self.ForbiddenTransports.push(TransportKind);
187
188 self
189 }
190
191 pub fn WithForbiddenTransport(self, TransportKind:TransportType) -> Self {
193 self.AddForbiddenTransport(TransportKind)
194 }
195
196 pub fn IsAllowed(&self, TransportKind:TransportType) -> bool {
198 if self.ForbiddenTransports.contains(&TransportKind) {
199 return false;
200 }
201
202 if self.AllowedTransports.is_empty() {
203 true
204 } else {
205 self.AllowedTransports.contains(&TransportKind)
206 }
207 }
208
209 pub fn EffectiveTimeout(&self, RequestTimeoutMilliseconds:Option<u64>) -> Duration {
212 RequestTimeoutMilliseconds
213 .map(Duration::from_millis)
214 .unwrap_or(self.DefaultTimeout)
215 }
216
217 pub fn EffectiveRetryDelay(&self, Attempt:u32) -> Duration {
220 let Multiplier = 1u32.checked_shl(Attempt.min(30)).unwrap_or(u32::MAX);
221
222 let mut Delay = self.RetryBaseDelay.checked_mul(Multiplier).unwrap_or(self.RetryMaximumDelay);
223
224 if Delay > self.RetryMaximumDelay {
225 Delay = self.RetryMaximumDelay;
226 }
227
228 if self.RetryJitterEnabled {
229 let Nanoseconds = std::time::SystemTime::now()
230 .duration_since(std::time::UNIX_EPOCH)
231 .map(|Duration| Duration.subsec_nanos())
232 .unwrap_or(0);
233
234 let JitterFraction = (Nanoseconds % 1000) as f64 / 500.0 - 1.0;
235
236 let JitterAmount = Delay.as_millis() as f64 * 0.25;
237
238 let AdjustedMilliseconds = (Delay.as_millis() as f64 + JitterFraction * JitterAmount).max(1.0) as u64;
239
240 Delay = Duration::from_millis(AdjustedMilliseconds);
241 }
242
243 Delay
244 }
245}
246
247#[cfg(test)]
248mod tests {
249
250 use super::*;
251
252 #[test]
253 fn TestTransportConfigDefaults() {
254 let Configuration = TransportConfig::default();
255
256 assert_eq!(Configuration.DefaultTimeout, Duration::from_secs(30));
257
258 assert_eq!(Configuration.MaximumRetries, 3);
259
260 assert!(Configuration.HealthChecksEnabled);
261
262 assert!(Configuration.MetricsEnabled);
263 }
264
265 #[test]
266 fn TestTransportConfigBuilder() {
267 let Configuration = TransportConfig::default()
268 .WithDefaultTimeout(Duration::from_secs(60))
269 .WithMaximumRetries(5)
270 .WithRetryJitter(false);
271
272 assert_eq!(Configuration.DefaultTimeout, Duration::from_secs(60));
273
274 assert_eq!(Configuration.MaximumRetries, 5);
275
276 assert!(!Configuration.RetryJitterEnabled);
277 }
278
279 #[test]
280 fn TestIsAllowed() {
281 let Configuration = TransportConfig::default();
282
283 assert!(Configuration.IsAllowed(TransportType::Grpc));
284
285 let Configuration = Configuration.WithForbiddenTransport(TransportType::Grpc);
286
287 assert!(!Configuration.IsAllowed(TransportType::Grpc));
288
289 assert!(Configuration.IsAllowed(TransportType::Ipc));
290
291 let Configuration = Configuration.WithAllowedTransports(vec![TransportType::Ipc]);
292
293 assert!(!Configuration.IsAllowed(TransportType::Grpc));
294
295 assert!(Configuration.IsAllowed(TransportType::Ipc));
296 }
297
298 #[test]
299 fn TestEffectiveTimeout() {
300 let Configuration = TransportConfig::default().WithDefaultTimeout(Duration::from_secs(30));
301
302 assert_eq!(Configuration.EffectiveTimeout(None), Duration::from_secs(30));
303
304 assert_eq!(Configuration.EffectiveTimeout(Some(5000)), Duration::from_millis(5000));
305 }
306
307 #[test]
308 fn TestEffectiveRetryDelay() {
309 let Configuration = TransportConfig::default()
310 .WithRetryBaseDelay(Duration::from_millis(100))
311 .WithRetryMaximumDelay(Duration::from_secs(10))
312 .WithRetryJitter(false);
313
314 assert_eq!(Configuration.EffectiveRetryDelay(0), Duration::from_millis(100));
315
316 assert_eq!(Configuration.EffectiveRetryDelay(1), Duration::from_millis(200));
317
318 assert_eq!(Configuration.EffectiveRetryDelay(2), Duration::from_millis(400));
319
320 assert_eq!(Configuration.EffectiveRetryDelay(10), Duration::from_secs(10));
321 }
322}