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