rustkernel_core/
messages.rs1use serde::{Deserialize, Serialize};
7use std::sync::atomic::{AtomicU64, Ordering};
8
9pub use ringkernel_core::{MessageHeader, MessageId, RingMessage};
11
12static MESSAGE_COUNTER: AtomicU64 = AtomicU64::new(1);
14
15#[must_use]
17pub fn next_message_id() -> MessageId {
18 MessageId(MESSAGE_COUNTER.fetch_add(1, Ordering::SeqCst))
19}
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
23pub struct CorrelationId(pub u64);
24
25impl CorrelationId {
26 #[must_use]
28 pub fn new() -> Self {
29 Self(MESSAGE_COUNTER.fetch_add(1, Ordering::SeqCst))
30 }
31
32 #[must_use]
34 pub const fn from_raw(value: u64) -> Self {
35 Self(value)
36 }
37}
38
39impl Default for CorrelationId {
40 fn default() -> Self {
41 Self::new()
42 }
43}
44
45pub trait BatchMessage:
63 serde::Serialize + for<'de> serde::Deserialize<'de> + Send + Sync + 'static
64{
65 fn message_type_id() -> u64;
67
68 fn to_json(&self) -> Result<Vec<u8>, serde_json::Error> {
70 serde_json::to_vec(self)
71 }
72
73 fn from_json(bytes: &[u8]) -> Result<Self, serde_json::Error>
75 where
76 Self: Sized,
77 {
78 serde_json::from_slice(bytes)
79 }
80
81 fn size_hint(&self) -> usize {
83 std::mem::size_of::<Self>()
84 }
85}
86
87pub trait KernelRequest: RingMessage + Send + Sync {
89 fn correlation_id(&self) -> CorrelationId;
91
92 fn set_correlation_id(&mut self, id: CorrelationId);
94}
95
96pub trait KernelResponse: RingMessage + Send + Sync {
98 fn correlation_id(&self) -> CorrelationId;
100
101 fn is_success(&self) -> bool;
103
104 fn error_message(&self) -> Option<&str>;
106}
107
108#[derive(Clone, Debug, Serialize, Deserialize)]
110pub struct KernelResult<T> {
111 pub correlation_id: CorrelationId,
113 pub data: Option<T>,
115 pub error: Option<String>,
117}
118
119impl<T> KernelResult<T> {
120 pub fn success(correlation_id: CorrelationId, data: T) -> Self {
122 Self {
123 correlation_id,
124 data: Some(data),
125 error: None,
126 }
127 }
128
129 pub fn failure(correlation_id: CorrelationId, error: impl Into<String>) -> Self {
131 Self {
132 correlation_id,
133 data: None,
134 error: Some(error.into()),
135 }
136 }
137
138 #[must_use]
140 pub fn is_success(&self) -> bool {
141 self.data.is_some() && self.error.is_none()
142 }
143
144 pub fn into_result(self) -> Result<T, String> {
146 match (self.data, self.error) {
147 (Some(data), None) => Ok(data),
148 (_, Some(err)) => Err(err),
149 (None, None) => Err("No data or error provided".to_string()),
150 }
151 }
152}
153
154#[allow(missing_docs)]
159pub mod type_ids {
160 pub const PAGERANK_REQUEST: u32 = 100;
162 pub const PAGERANK_RESPONSE: u32 = 101;
163 pub const DEGREE_CENTRALITY_REQUEST: u32 = 102;
164 pub const DEGREE_CENTRALITY_RESPONSE: u32 = 103;
165 pub const BETWEENNESS_REQUEST: u32 = 104;
166 pub const BETWEENNESS_RESPONSE: u32 = 105;
167 pub const CLOSENESS_REQUEST: u32 = 106;
168 pub const CLOSENESS_RESPONSE: u32 = 107;
169 pub const EIGENVECTOR_REQUEST: u32 = 108;
170 pub const EIGENVECTOR_RESPONSE: u32 = 109;
171 pub const KATZ_REQUEST: u32 = 110;
172 pub const KATZ_RESPONSE: u32 = 111;
173 pub const COMMUNITY_REQUEST: u32 = 120;
174 pub const COMMUNITY_RESPONSE: u32 = 121;
175 pub const MOTIF_REQUEST: u32 = 130;
176 pub const MOTIF_RESPONSE: u32 = 131;
177 pub const SIMILARITY_REQUEST: u32 = 140;
178 pub const SIMILARITY_RESPONSE: u32 = 141;
179 pub const METRICS_REQUEST: u32 = 150;
180 pub const METRICS_RESPONSE: u32 = 151;
181
182 pub const KMEANS_REQUEST: u32 = 200;
184 pub const KMEANS_RESPONSE: u32 = 201;
185 pub const DBSCAN_REQUEST: u32 = 202;
186 pub const DBSCAN_RESPONSE: u32 = 203;
187 pub const HIERARCHICAL_REQUEST: u32 = 204;
188 pub const HIERARCHICAL_RESPONSE: u32 = 205;
189 pub const ISOLATION_FOREST_REQUEST: u32 = 210;
190 pub const ISOLATION_FOREST_RESPONSE: u32 = 211;
191 pub const LOF_REQUEST: u32 = 212;
192 pub const LOF_RESPONSE: u32 = 213;
193 pub const REGRESSION_REQUEST: u32 = 220;
194 pub const REGRESSION_RESPONSE: u32 = 221;
195
196 pub const CIRCULAR_FLOW_REQUEST: u32 = 300;
198 pub const CIRCULAR_FLOW_RESPONSE: u32 = 301;
199 pub const RECIPROCITY_REQUEST: u32 = 302;
200 pub const RECIPROCITY_RESPONSE: u32 = 303;
201 pub const RAPID_MOVEMENT_REQUEST: u32 = 304;
202 pub const RAPID_MOVEMENT_RESPONSE: u32 = 305;
203 pub const AML_PATTERN_REQUEST: u32 = 306;
204 pub const AML_PATTERN_RESPONSE: u32 = 307;
205 pub const SANCTIONS_REQUEST: u32 = 310;
206 pub const SANCTIONS_RESPONSE: u32 = 311;
207 pub const KYC_REQUEST: u32 = 320;
208 pub const KYC_RESPONSE: u32 = 321;
209 pub const TRANSACTION_MONITOR_REQUEST: u32 = 330;
210 pub const TRANSACTION_MONITOR_RESPONSE: u32 = 331;
211
212 pub const CREDIT_RISK_REQUEST: u32 = 400;
214 pub const CREDIT_RISK_RESPONSE: u32 = 401;
215 pub const MONTE_CARLO_VAR_REQUEST: u32 = 410;
216 pub const MONTE_CARLO_VAR_RESPONSE: u32 = 411;
217 pub const PORTFOLIO_RISK_REQUEST: u32 = 412;
218 pub const PORTFOLIO_RISK_RESPONSE: u32 = 413;
219 pub const STRESS_TEST_REQUEST: u32 = 420;
220 pub const STRESS_TEST_RESPONSE: u32 = 421;
221
222 pub const ARIMA_REQUEST: u32 = 500;
224 pub const ARIMA_RESPONSE: u32 = 501;
225 pub const PROPHET_REQUEST: u32 = 502;
226 pub const PROPHET_RESPONSE: u32 = 503;
227 pub const CHANGE_POINT_REQUEST: u32 = 510;
228 pub const CHANGE_POINT_RESPONSE: u32 = 511;
229 pub const VOLATILITY_REQUEST: u32 = 520;
230 pub const VOLATILITY_RESPONSE: u32 = 521;
231
232 pub const ORDER_SUBMIT_REQUEST: u32 = 600;
234 pub const ORDER_SUBMIT_RESPONSE: u32 = 601;
235 pub const ORDER_CANCEL_REQUEST: u32 = 602;
236 pub const ORDER_CANCEL_RESPONSE: u32 = 603;
237 pub const ORDER_MODIFY_REQUEST: u32 = 604;
238 pub const ORDER_MODIFY_RESPONSE: u32 = 605;
239 pub const BOOK_QUERY_REQUEST: u32 = 610;
240 pub const BOOK_QUERY_RESPONSE: u32 = 611;
241
242 pub const CLEARING_VALIDATION_REQUEST: u32 = 700;
244 pub const CLEARING_VALIDATION_RESPONSE: u32 = 701;
245 pub const DVP_MATCHING_REQUEST: u32 = 710;
246 pub const DVP_MATCHING_RESPONSE: u32 = 711;
247 pub const NETTING_REQUEST: u32 = 720;
248 pub const NETTING_RESPONSE: u32 = 721;
249 pub const SETTLEMENT_REQUEST: u32 = 730;
250 pub const SETTLEMENT_RESPONSE: u32 = 731;
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256
257 #[test]
258 fn test_correlation_id() {
259 let id1 = CorrelationId::new();
260 let id2 = CorrelationId::new();
261 assert_ne!(id1, id2);
262 }
263
264 #[test]
265 fn test_message_id_generation() {
266 let id1 = next_message_id();
267 let id2 = next_message_id();
268 assert!(id2.0 > id1.0);
269 }
270
271 #[test]
272 fn test_kernel_result_success() {
273 let result = KernelResult::success(CorrelationId::new(), 42);
274 assert!(result.is_success());
275 assert_eq!(result.into_result(), Ok(42));
276 }
277
278 #[test]
279 fn test_kernel_result_failure() {
280 let result: KernelResult<i32> = KernelResult::failure(CorrelationId::new(), "error");
281 assert!(!result.is_success());
282 assert_eq!(result.into_result(), Err("error".to_string()));
283 }
284
285 #[test]
286 fn test_batch_message_trait() {
287 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
289 struct TestMessage {
290 value: i32,
291 }
292
293 impl BatchMessage for TestMessage {
295 fn message_type_id() -> u64 {
296 42
297 }
298 }
299
300 let msg = TestMessage { value: 123 };
301
302 assert_eq!(TestMessage::message_type_id(), 42);
304
305 let json = msg.to_json().expect("serialization failed");
307 assert!(!json.is_empty());
308
309 let decoded: TestMessage = TestMessage::from_json(&json).expect("deserialization failed");
311 assert_eq!(decoded.value, 123);
312 }
313}