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 MaximumRetries:3,
65 RetryBaseDelay:Duration::from_millis(100),
66 RetryMaximumDelay:Duration::from_secs(10),
67 RetryJitterEnabled:true,
68 CircuitBreakerFailureThreshold:5,
69 CircuitBreakerResetTimeout:Duration::from_secs(60),
70 HealthChecksEnabled:true,
71 HealthCheckInterval:Duration::from_secs(30),
72 MetricsEnabled:true,
73 TransportConfigurations:HashMap::new(),
74 AllowedTransports:Vec::new(),
75 ForbiddenTransports:Vec::new(),
76 }
77 }
78}
79
80impl TransportConfig {
81 pub fn New() -> Self { Self::default() }
83
84 pub fn WithDefaultTimeout(mut self, Timeout:Duration) -> Self {
86 self.DefaultTimeout = Timeout;
87 self
88 }
89
90 pub fn WithMaximumRetries(mut self, MaximumRetries:u32) -> Self {
92 self.MaximumRetries = MaximumRetries;
93 self
94 }
95
96 pub fn WithRetryBaseDelay(mut self, Delay:Duration) -> Self {
98 self.RetryBaseDelay = Delay;
99 self
100 }
101
102 pub fn WithRetryMaximumDelay(mut self, Delay:Duration) -> Self {
104 self.RetryMaximumDelay = Delay;
105 self
106 }
107
108 pub fn WithRetryJitter(mut self, Enabled:bool) -> Self {
110 self.RetryJitterEnabled = Enabled;
111 self
112 }
113
114 pub fn WithCircuitBreakerThreshold(mut self, Threshold:u32) -> Self {
116 self.CircuitBreakerFailureThreshold = Threshold;
117 self
118 }
119
120 pub fn WithCircuitBreakerResetTimeout(mut self, Timeout:Duration) -> Self {
122 self.CircuitBreakerResetTimeout = Timeout;
123 self
124 }
125
126 pub fn WithHealthChecksEnabled(mut self, Enabled:bool) -> Self {
128 self.HealthChecksEnabled = Enabled;
129 self
130 }
131
132 pub fn WithHealthCheckInterval(mut self, Interval:Duration) -> Self {
134 self.HealthCheckInterval = Interval;
135 self
136 }
137
138 pub fn WithMetricsEnabled(mut self, Enabled:bool) -> Self {
140 self.MetricsEnabled = Enabled;
141 self
142 }
143
144 pub fn WithTransportConfiguration(mut self, TransportKind:TransportType, Configuration:serde_json::Value) -> Self {
146 self.TransportConfigurations.insert(TransportKind, Configuration);
147 self
148 }
149
150 pub fn GetTransportConfiguration(&self, TransportKind:TransportType) -> Option<&serde_json::Value> {
152 self.TransportConfigurations.get(&TransportKind)
153 }
154
155 pub fn WithAllowedTransports(mut self, Transports:Vec<TransportType>) -> Self {
157 self.AllowedTransports = Transports;
158 self
159 }
160
161 pub fn AddForbiddenTransport(mut self, TransportKind:TransportType) -> Self {
163 self.ForbiddenTransports.push(TransportKind);
164 self
165 }
166
167 pub fn WithForbiddenTransport(self, TransportKind:TransportType) -> Self {
169 self.AddForbiddenTransport(TransportKind)
170 }
171
172 pub fn IsAllowed(&self, TransportKind:TransportType) -> bool {
174 if self.ForbiddenTransports.contains(&TransportKind) {
175 return false;
176 }
177 if self.AllowedTransports.is_empty() {
178 true
179 } else {
180 self.AllowedTransports.contains(&TransportKind)
181 }
182 }
183
184 pub fn EffectiveTimeout(&self, RequestTimeoutMilliseconds:Option<u64>) -> Duration {
187 RequestTimeoutMilliseconds
188 .map(Duration::from_millis)
189 .unwrap_or(self.DefaultTimeout)
190 }
191
192 pub fn EffectiveRetryDelay(&self, Attempt:u32) -> Duration {
195 let Multiplier = 1u32.checked_shl(Attempt.min(30)).unwrap_or(u32::MAX);
196 let mut Delay = self.RetryBaseDelay.checked_mul(Multiplier).unwrap_or(self.RetryMaximumDelay);
197
198 if Delay > self.RetryMaximumDelay {
199 Delay = self.RetryMaximumDelay;
200 }
201
202 if self.RetryJitterEnabled {
203 let Nanoseconds = std::time::SystemTime::now()
204 .duration_since(std::time::UNIX_EPOCH)
205 .map(|Duration| Duration.subsec_nanos())
206 .unwrap_or(0);
207 let JitterFraction = (Nanoseconds % 1000) as f64 / 500.0 - 1.0;
208 let JitterAmount = Delay.as_millis() as f64 * 0.25;
209 let AdjustedMilliseconds = (Delay.as_millis() as f64 + JitterFraction * JitterAmount).max(1.0) as u64;
210 Delay = Duration::from_millis(AdjustedMilliseconds);
211 }
212
213 Delay
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220
221 #[test]
222 fn TestTransportConfigDefaults() {
223 let Configuration = TransportConfig::default();
224 assert_eq!(Configuration.DefaultTimeout, Duration::from_secs(30));
225 assert_eq!(Configuration.MaximumRetries, 3);
226 assert!(Configuration.HealthChecksEnabled);
227 assert!(Configuration.MetricsEnabled);
228 }
229
230 #[test]
231 fn TestTransportConfigBuilder() {
232 let Configuration = TransportConfig::default()
233 .WithDefaultTimeout(Duration::from_secs(60))
234 .WithMaximumRetries(5)
235 .WithRetryJitter(false);
236
237 assert_eq!(Configuration.DefaultTimeout, Duration::from_secs(60));
238 assert_eq!(Configuration.MaximumRetries, 5);
239 assert!(!Configuration.RetryJitterEnabled);
240 }
241
242 #[test]
243 fn TestIsAllowed() {
244 let Configuration = TransportConfig::default();
245 assert!(Configuration.IsAllowed(TransportType::Grpc));
246
247 let Configuration = Configuration.WithForbiddenTransport(TransportType::Grpc);
248 assert!(!Configuration.IsAllowed(TransportType::Grpc));
249 assert!(Configuration.IsAllowed(TransportType::Ipc));
250
251 let Configuration = Configuration.WithAllowedTransports(vec![TransportType::Ipc]);
252 assert!(!Configuration.IsAllowed(TransportType::Grpc));
253 assert!(Configuration.IsAllowed(TransportType::Ipc));
254 }
255
256 #[test]
257 fn TestEffectiveTimeout() {
258 let Configuration = TransportConfig::default().WithDefaultTimeout(Duration::from_secs(30));
259
260 assert_eq!(Configuration.EffectiveTimeout(None), Duration::from_secs(30));
261 assert_eq!(Configuration.EffectiveTimeout(Some(5000)), Duration::from_millis(5000));
262 }
263
264 #[test]
265 fn TestEffectiveRetryDelay() {
266 let Configuration = TransportConfig::default()
267 .WithRetryBaseDelay(Duration::from_millis(100))
268 .WithRetryMaximumDelay(Duration::from_secs(10))
269 .WithRetryJitter(false);
270
271 assert_eq!(Configuration.EffectiveRetryDelay(0), Duration::from_millis(100));
272 assert_eq!(Configuration.EffectiveRetryDelay(1), Duration::from_millis(200));
273 assert_eq!(Configuration.EffectiveRetryDelay(2), Duration::from_millis(400));
274 assert_eq!(Configuration.EffectiveRetryDelay(10), Duration::from_secs(10));
275 }
276}