1#![cfg(native)]
2
3use super::error::SignalError;
33use async_trait::async_trait;
34use serde::{Deserialize, Serialize, de::DeserializeOwned};
35use std::fmt;
36use std::marker::PhantomData;
37use std::sync::Arc;
38use tokio::sync::RwLock;
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct DistributedEvent<T> {
61 pub signal_name: String,
63 pub payload: T,
65 pub source_service: String,
67 pub timestamp: u64,
69 pub event_id: String,
71}
72
73impl<T> DistributedEvent<T> {
74 pub fn new(
85 signal_name: impl Into<String>,
86 payload: T,
87 source_service: impl Into<String>,
88 ) -> Self {
89 use std::time::{SystemTime, UNIX_EPOCH};
90
91 let timestamp = SystemTime::now()
92 .duration_since(UNIX_EPOCH)
93 .unwrap_or_default()
94 .as_millis() as u64;
95
96 Self {
97 signal_name: signal_name.into(),
98 payload,
99 source_service: source_service.into(),
100 timestamp,
101 event_id: uuid::Uuid::now_v7().to_string(),
102 }
103 }
104}
105
106#[async_trait]
110pub trait MessageBroker: Send + Sync {
111 async fn publish(&self, channel: &str, message: &[u8]) -> Result<(), SignalError>;
113
114 async fn subscribe(
116 &self,
117 channel: &str,
118 handler: Arc<dyn Fn(Vec<u8>) -> Result<(), SignalError> + Send + Sync>,
119 ) -> Result<(), SignalError>;
120
121 async fn unsubscribe(&self, channel: &str) -> Result<(), SignalError>;
123}
124
125type SubscriberFn = Arc<dyn Fn(Vec<u8>) -> Result<(), SignalError> + Send + Sync>;
129
130type ChannelsMap = std::collections::HashMap<String, Vec<SubscriberFn>>;
132
133pub struct InMemoryBroker {
141 channels: Arc<RwLock<ChannelsMap>>,
142}
143
144impl InMemoryBroker {
145 pub fn new() -> Self {
155 Self {
156 channels: Arc::new(RwLock::new(std::collections::HashMap::new())),
157 }
158 }
159}
160
161impl Default for InMemoryBroker {
162 fn default() -> Self {
163 Self::new()
164 }
165}
166
167#[async_trait]
168impl MessageBroker for InMemoryBroker {
169 async fn publish(&self, channel: &str, message: &[u8]) -> Result<(), SignalError> {
170 let channels = self.channels.read().await;
171 if let Some(handlers) = channels.get(channel) {
172 for handler in handlers {
173 handler(message.to_vec())?;
174 }
175 }
176 Ok(())
177 }
178
179 async fn subscribe(
180 &self,
181 channel: &str,
182 handler: Arc<dyn Fn(Vec<u8>) -> Result<(), SignalError> + Send + Sync>,
183 ) -> Result<(), SignalError> {
184 let mut channels = self.channels.write().await;
185 channels
186 .entry(channel.to_string())
187 .or_insert_with(Vec::new)
188 .push(handler);
189 Ok(())
190 }
191
192 async fn unsubscribe(&self, channel: &str) -> Result<(), SignalError> {
193 let mut channels = self.channels.write().await;
194 channels.remove(channel);
195 Ok(())
196 }
197}
198
199pub struct DistributedSignal<T, B>
212where
213 T: Serialize + DeserializeOwned + Send + Sync + 'static,
214 B: MessageBroker + 'static,
215{
216 signal_name: String,
217 broker: Arc<B>,
218 service_id: String,
219 _phantom: PhantomData<T>,
220}
221
222impl<T, B> DistributedSignal<T, B>
223where
224 T: Serialize + DeserializeOwned + Send + Sync + 'static,
225 B: MessageBroker + 'static,
226{
227 pub fn new(signal_name: impl Into<String>, broker: B, service_id: impl Into<String>) -> Self {
238 Self {
239 signal_name: signal_name.into(),
240 broker: Arc::new(broker),
241 service_id: service_id.into(),
242 _phantom: PhantomData,
243 }
244 }
245
246 pub fn name(&self) -> &str {
258 &self.signal_name
259 }
260
261 pub fn service_id(&self) -> &str {
273 &self.service_id
274 }
275
276 pub async fn publish(&self, payload: T) -> Result<(), SignalError> {
293 let event = DistributedEvent::new(&self.signal_name, payload, &self.service_id);
294 let message = serde_json::to_vec(&event)
295 .map_err(|e| SignalError::new(format!("Serialization error: {}", e)))?;
296
297 self.broker.publish(&self.signal_name, &message).await
298 }
299
300 pub async fn subscribe<F>(&self, handler: F) -> Result<(), SignalError>
320 where
321 F: Fn(DistributedEvent<T>) -> Result<(), SignalError> + Send + Sync + 'static,
322 {
323 let handler = Arc::new(handler);
324 let wrapped_handler = Arc::new(move |message: Vec<u8>| {
325 let event: DistributedEvent<T> = serde_json::from_slice(&message)
326 .map_err(|e| SignalError::new(format!("Deserialization error: {}", e)))?;
327 handler(event)
328 });
329
330 self.broker
331 .subscribe(&self.signal_name, wrapped_handler)
332 .await
333 }
334
335 pub async fn unsubscribe(&self) -> Result<(), SignalError> {
352 self.broker.unsubscribe(&self.signal_name).await
353 }
354}
355
356impl<T, B> Clone for DistributedSignal<T, B>
357where
358 T: Serialize + DeserializeOwned + Send + Sync + 'static,
359 B: MessageBroker + 'static,
360{
361 fn clone(&self) -> Self {
362 Self {
363 signal_name: self.signal_name.clone(),
364 broker: Arc::clone(&self.broker),
365 service_id: self.service_id.clone(),
366 _phantom: PhantomData,
367 }
368 }
369}
370
371impl<T, B> fmt::Debug for DistributedSignal<T, B>
372where
373 T: Serialize + DeserializeOwned + Send + Sync + 'static,
374 B: MessageBroker + 'static,
375{
376 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
377 f.debug_struct("DistributedSignal")
378 .field("signal_name", &self.signal_name)
379 .field("service_id", &self.service_id)
380 .finish()
381 }
382}
383
384#[cfg(test)]
385mod tests {
386 use super::*;
387 use parking_lot::Mutex;
388 use std::sync::Arc;
389 use std::sync::atomic::{AtomicUsize, Ordering};
390
391 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
392 struct TestPayload {
393 message: String,
394 count: i32,
395 }
396
397 #[test]
398 fn test_distributed_event_creation() {
399 let event = DistributedEvent::new("test_signal", "test_payload", "service-1");
400 assert_eq!(event.signal_name, "test_signal");
401 assert_eq!(event.payload, "test_payload");
402 assert_eq!(event.source_service, "service-1");
403 assert!(event.timestamp > 0);
404 assert!(!event.event_id.is_empty());
405 }
406
407 #[tokio::test]
408 async fn test_in_memory_broker() {
409 let broker = InMemoryBroker::new();
410 let received = Arc::new(Mutex::new(Vec::new()));
411
412 let r = received.clone();
413 let handler = Arc::new(move |msg: Vec<u8>| {
414 r.lock().push(msg);
415 Ok(())
416 });
417
418 broker.subscribe("test_channel", handler).await.unwrap();
419 broker.publish("test_channel", b"hello").await.unwrap();
420
421 let messages = received.lock();
422 assert_eq!(messages.len(), 1);
423 assert_eq!(messages[0], b"hello");
424 }
425
426 #[tokio::test]
427 async fn test_distributed_signal_publish_subscribe() {
428 let broker = InMemoryBroker::new();
429 let signal = DistributedSignal::new("user_event", broker, "service-1");
430
431 let received = Arc::new(Mutex::new(Vec::new()));
432 let r = received.clone();
433
434 signal
435 .subscribe(move |event| {
436 r.lock().push(event.payload);
437 Ok(())
438 })
439 .await
440 .unwrap();
441
442 let payload = TestPayload {
443 message: "Hello".to_string(),
444 count: 42,
445 };
446
447 signal.publish(payload.clone()).await.unwrap();
448
449 let events = received.lock();
450 assert_eq!(events.len(), 1);
451 assert_eq!(events[0], payload);
452 }
453
454 #[tokio::test]
455 async fn test_distributed_signal_multiple_subscribers() {
456 let broker = InMemoryBroker::new();
457 let signal = DistributedSignal::new("broadcast", broker, "svc-1");
458
459 let counter = Arc::new(AtomicUsize::new(0));
460
461 let c1 = counter.clone();
462 signal
463 .subscribe(move |_event: DistributedEvent<String>| {
464 c1.fetch_add(1, Ordering::SeqCst);
465 Ok(())
466 })
467 .await
468 .unwrap();
469
470 let c2 = counter.clone();
471 signal
472 .subscribe(move |_event| {
473 c2.fetch_add(1, Ordering::SeqCst);
474 Ok(())
475 })
476 .await
477 .unwrap();
478
479 signal.publish("test".to_string()).await.unwrap();
480
481 assert_eq!(counter.load(Ordering::SeqCst), 2);
482 }
483
484 #[tokio::test]
485 async fn test_distributed_signal_name_and_service_id() {
486 let broker = InMemoryBroker::new();
487 let signal = DistributedSignal::<String, _>::new("my_signal", broker, "my_service");
488
489 assert_eq!(signal.name(), "my_signal");
490 assert_eq!(signal.service_id(), "my_service");
491 }
492
493 #[tokio::test]
494 async fn test_distributed_signal_unsubscribe() {
495 let broker = InMemoryBroker::new();
496 let signal = DistributedSignal::new("temp_signal", broker, "svc-1");
497
498 let counter = Arc::new(AtomicUsize::new(0));
499 let c = counter.clone();
500
501 signal
502 .subscribe(move |_event: DistributedEvent<String>| {
503 c.fetch_add(1, Ordering::SeqCst);
504 Ok(())
505 })
506 .await
507 .unwrap();
508
509 signal.publish("first".to_string()).await.unwrap();
510 assert_eq!(counter.load(Ordering::SeqCst), 1);
511
512 signal.unsubscribe().await.unwrap();
513 signal.publish("second".to_string()).await.unwrap();
514
515 assert_eq!(counter.load(Ordering::SeqCst), 1);
517 }
518
519 #[tokio::test]
520 async fn test_distributed_event_metadata() {
521 let broker = InMemoryBroker::new();
522 let signal = DistributedSignal::new("metadata_test", broker, "test-service");
523
524 let received_event = Arc::new(Mutex::new(None));
525 let r = received_event.clone();
526
527 signal
528 .subscribe(move |event: DistributedEvent<String>| {
529 *r.lock() = Some(event);
530 Ok(())
531 })
532 .await
533 .unwrap();
534
535 signal.publish("payload".to_string()).await.unwrap();
536
537 let event = received_event.lock().clone().unwrap();
538 assert_eq!(event.signal_name, "metadata_test");
539 assert_eq!(event.source_service, "test-service");
540 assert_eq!(event.payload, "payload");
541 assert!(event.timestamp > 0);
542 assert!(!event.event_id.is_empty());
543 }
544}