CommonLibrary/Transport/
UnifiedRequest.rs1use std::collections::HashMap;
6
7use serde::{Deserialize, Serialize};
8
9use super::Common::{
10 CorrelationId,
11 CorrelationIdGenerator,
12 SystemTimestampGenerator,
13 Timestamp,
14 TimestampGenerator,
15 TransportType,
16 UuidCorrelationIdGenerator,
17};
18
19#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
21pub struct UnifiedRequest {
22 #[serde(skip_serializing_if = "Option::is_none")]
24 pub CorrelationIdentifier:Option<CorrelationId>,
25
26 pub Method:String,
28
29 pub Payload:Vec<u8>,
31
32 #[serde(skip_serializing_if = "HashMap::is_empty")]
34 pub Metadata:HashMap<String, String>,
35
36 pub CreatedAt:Timestamp,
38
39 #[serde(skip_serializing_if = "Option::is_none")]
41 pub TransportHint:Option<TransportType>,
42}
43
44impl UnifiedRequest {
45 pub fn New(Method:impl Into<String>) -> Self {
47 Self {
48 CorrelationIdentifier:Some(UuidCorrelationIdGenerator::Generate()),
49
50 Method:Method.into(),
51
52 Payload:Vec::new(),
53
54 Metadata:HashMap::new(),
55
56 CreatedAt:SystemTimestampGenerator::Now(),
57
58 TransportHint:None,
59 }
60 }
61
62 pub fn WithCorrelationIdentifier(mut self, CorrelationIdentifier:CorrelationId) -> Self {
64 self.CorrelationIdentifier = Some(CorrelationIdentifier);
65
66 self
67 }
68
69 pub fn WithPayload(mut self, Payload:Vec<u8>) -> Self {
71 self.Payload = Payload;
72
73 self
74 }
75
76 pub fn WithMetadata(mut self, Key:impl Into<String>, Value:impl Into<String>) -> Self {
78 self.Metadata.insert(Key.into(), Value.into());
79
80 self
81 }
82
83 pub fn WithMetadataMap(mut self, Metadata:HashMap<String, String>) -> Self {
85 self.Metadata = Metadata;
86
87 self
88 }
89
90 pub fn WithTimeout(mut self, TimeoutMilliseconds:u64) -> Self {
92 self.Metadata.insert("timeout_ms".to_string(), TimeoutMilliseconds.to_string());
93
94 self
95 }
96
97 pub fn WithPriority(mut self, Priority:u32) -> Self {
99 self.Metadata.insert("priority".to_string(), Priority.to_string());
100
101 self
102 }
103
104 pub fn WithTransportHint(mut self, TransportKind:TransportType) -> Self {
106 self.TransportHint = Some(TransportKind);
107
108 self
109 }
110
111 pub fn TimeoutMilliseconds(&self) -> Option<u64> {
113 self.Metadata.get("timeout_ms").and_then(|Value| Value.parse().ok())
114 }
115
116 pub fn Priority(&self) -> Option<u32> { self.Metadata.get("priority").and_then(|Value| Value.parse().ok()) }
118
119 pub fn Validate(&self) -> Result<(), String> {
121 if self.Method.is_empty() {
122 return Err("method cannot be empty".to_string());
123 }
124
125 if let Some(Identifier) = &self.CorrelationIdentifier {
126 if Identifier.is_empty() {
127 return Err("correlation_id cannot be empty if specified".to_string());
128 }
129 }
130
131 Ok(())
132 }
133}
134
135#[cfg(test)]
136mod tests {
137
138 use super::*;
139
140 #[test]
141 fn TestUnifiedRequestCreation() {
142 let Request = UnifiedRequest::New("test.method");
143
144 assert!(!Request.Method.is_empty());
145
146 assert!(Request.CorrelationIdentifier.is_some());
147
148 assert_eq!(Request.Payload, Vec::<u8>::new());
149
150 assert!(Request.Metadata.is_empty());
151
152 assert!(Request.TransportHint.is_none());
153 }
154
155 #[test]
156 fn TestUnifiedRequestBuilder() {
157 let Request = UnifiedRequest::New("fileSystem.readFile")
158 .WithPayload(b"{\"path\": \"/tmp/test.txt\"}".to_vec())
159 .WithTimeout(5000)
160 .WithPriority(10)
161 .WithMetadata("traceparent", "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01")
162 .WithTransportHint(TransportType::Grpc);
163
164 assert_eq!(Request.Method, "fileSystem.readFile");
165
166 assert_eq!(Request.Payload, b"{\"path\": \"/tmp/test.txt\"}");
167
168 assert_eq!(Request.TimeoutMilliseconds(), Some(5000));
169
170 assert_eq!(Request.Priority(), Some(10));
171
172 assert_eq!(Request.TransportHint, Some(TransportType::Grpc));
173
174 assert!(Request.Metadata.contains_key("traceparent"));
175 }
176
177 #[test]
178 fn TestUnifiedRequestValidation() {
179 let mut Request = UnifiedRequest::New("valid.method");
180
181 assert!(Request.Validate().is_ok());
182
183 Request.Method = String::new();
184
185 assert!(Request.Validate().is_err());
186
187 Request.Method = "valid.method".to_string();
188
189 Request.CorrelationIdentifier = Some("".to_string());
190
191 assert!(Request.Validate().is_err());
192 }
193}