Skip to main content

reifydb_core/event/
macro.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4/// Defines an event struct with cheap O(1) cloning using Arc<Inner> pattern.
5///
6/// This macro generates:
7/// - A hidden Inner struct containing all fields
8/// - A public wrapper struct with Arc<Inner>
9/// - Clone implementation that clones the Arc (cheap)
10/// - Constructor and accessor methods for all fields
11/// - Event trait implementation
12///
13/// # Example
14/// ```
15/// use reifydb_core::define_event;
16///
17/// define_event! {
18///     pub struct MyEvent {
19/// 	pub data: Vec<i32>,
20/// 	pub name: String,
21///     }
22/// }
23///
24/// let event = MyEvent::new(vec![1, 2, 3], "test".to_string());
25/// let clone = event.clone(); // O(1) operation, just increments Arc refcount
26/// assert_eq!(event.data().len(), 3);
27/// assert_eq!(event.name(), "test");
28/// ```
29#[macro_export]
30macro_rules! define_event {
31	// Handle empty structs (e.g., OnStartEvent)
32	(
33		$(#[$meta:meta])*
34		$vis:vis struct $name:ident {}
35	) => {
36		$(#[$meta])*
37		#[derive(Debug, Clone)]
38		$vis struct $name {}
39
40		impl $name {
41			#[allow(clippy::new_without_default)]
42			pub fn new() -> Self {
43				Self {}
44			}
45		}
46
47		impl $crate::event::Event for $name {
48			fn as_any(&self) -> &dyn std::any::Any {
49				self
50			}
51
52			fn into_any(self) -> Box<dyn std::any::Any + Send> {
53				Box::new(self)
54			}
55		}
56	};
57
58	// Handle non-empty structs with fields
59	(
60		$(#[$meta:meta])*
61		$vis:vis struct $name:ident {
62			$(
63				$(#[$field_meta:meta])*
64				$field_vis:vis $field:ident: $field_ty:ty
65			),* $(,)?
66		}
67	) => {
68		// create unique inner module name
69		::paste::paste! {
70			// Inner struct with all fields
71			#[doc(hidden)]
72			#[allow(non_snake_case)]
73			mod [<__inner_ $name:snake>] {
74				#[allow(unused_imports)]
75				use super::*;
76
77				#[derive(Debug)]
78				#[allow(dead_code)]
79				pub(super) struct Inner {
80					$(
81						$(#[$field_meta])*
82						pub(super) $field: $field_ty,
83					)*
84				}
85			}
86
87			// Wrapper struct with Arc
88			$(#[$meta])*
89			#[derive(Debug)]
90			$vis struct $name {
91				inner: std::sync::Arc<[<__inner_ $name:snake>]::Inner>,
92			}
93
94			// Clone implementation (cheap Arc clone)
95			impl Clone for $name {
96				fn clone(&self) -> Self {
97					Self {
98						inner: std::sync::Arc::clone(&self.inner),
99					}
100				}
101			}
102
103			// Constructor and accessor methods
104			impl $name {
105				#[allow(clippy::too_many_arguments)]
106				#[allow(clippy::new_without_default)]
107				pub fn new($($field: $field_ty),*) -> Self {
108					Self {
109						inner: std::sync::Arc::new([<__inner_ $name:snake>]::Inner {
110							$($field),*
111						}),
112					}
113				}
114
115				$(
116					#[allow(dead_code)]
117					pub fn $field(&self) -> &$field_ty {
118						&self.inner.$field
119					}
120				)*
121			}
122
123			// Event trait implementation
124			impl $crate::event::Event for $name {
125				fn as_any(&self) -> &dyn std::any::Any {
126					self
127				}
128
129				fn into_any(self) -> Box<dyn std::any::Any + Send> {
130					Box::new(self)
131				}
132			}
133		}
134	};
135}
136
137#[cfg(test)]
138mod tests {
139	use std::sync::{Arc, Mutex};
140
141	use crate::event::{Event, EventBus, EventListener};
142
143	define_event! {
144		pub struct DefineTestEvent {
145			pub data: Vec<i32>,
146			pub name: String,
147		}
148	}
149
150	define_event! {
151		pub struct EmptyDefineEvent {}
152	}
153
154	#[test]
155	fn test_define_event_cheap_clone() {
156		let large_vec = vec![0; 10_000];
157		let event = DefineTestEvent::new(large_vec, "test".to_string());
158
159		// Clone should be cheap (just Arc increment)
160		let clone1 = event.clone();
161		let clone2 = event.clone();
162
163		// Verify they share the same Arc by comparing pointers
164		assert!(Arc::ptr_eq(&event.inner, &clone1.inner));
165		assert!(Arc::ptr_eq(&event.inner, &clone2.inner));
166
167		// Data should be accessible
168		assert_eq!(event.data().len(), 10_000);
169		assert_eq!(clone1.data().len(), 10_000);
170		assert_eq!(clone2.data().len(), 10_000);
171	}
172
173	#[test]
174	fn test_define_event_field_access() {
175		let event = DefineTestEvent::new(vec![1, 2, 3], "my_event".to_string());
176
177		assert_eq!(event.data(), &vec![1, 2, 3]);
178		assert_eq!(event.name(), "my_event");
179
180		// Test that we get references, not owned values
181		let _data_ref: &Vec<i32> = event.data();
182		let _name_ref: &String = event.name();
183	}
184
185	#[test]
186	fn test_define_event_empty_struct() {
187		let event = EmptyDefineEvent::new();
188		let clone = event.clone();
189
190		// Should compile and work
191		drop(event);
192		drop(clone);
193	}
194
195	#[test]
196	fn test_define_event_implements_event_trait() {
197		let event = DefineTestEvent::new(vec![42], "test".to_string());
198
199		// Test Event trait methods
200		let any_ref = event.as_any();
201		assert!(any_ref.downcast_ref::<DefineTestEvent>().is_some());
202
203		let event2 = DefineTestEvent::new(vec![99], "test2".to_string());
204		let any_box = event2.into_any();
205		assert!(any_box.downcast::<DefineTestEvent>().is_ok());
206	}
207
208	#[test]
209	fn test_define_event_send_sync() {
210		// This test verifies that events are Send + Sync
211		fn assert_send<T: Send>() {}
212		fn assert_sync<T: Sync>() {}
213
214		assert_send::<DefineTestEvent>();
215		assert_sync::<DefineTestEvent>();
216
217		// Test that we can actually send across threads
218		let event = DefineTestEvent::new(vec![1, 2, 3], "thread_test".to_string());
219		let handle = std::thread::spawn(move || {
220			assert_eq!(event.data(), &vec![1, 2, 3]);
221		});
222		handle.join().unwrap();
223	}
224
225	#[test]
226	fn test_define_event_with_event_bus() {
227		let actor_system = reifydb_runtime::actor::system::ActorSystem::new(
228			reifydb_runtime::SharedRuntimeConfig::default().actor_system_config(),
229		);
230		let event_bus = EventBus::new(&actor_system);
231
232		// Create a listener for DefineTestEvent
233		#[derive(Clone)]
234		struct DefineTestListener {
235			counter: Arc<Mutex<i32>>,
236		}
237
238		impl EventListener<DefineTestEvent> for DefineTestListener {
239			fn on(&self, event: &DefineTestEvent) {
240				let mut c = self.counter.lock().unwrap();
241				*c += event.data().len() as i32;
242			}
243		}
244
245		let listener = DefineTestListener {
246			counter: Arc::new(Mutex::new(0)),
247		};
248
249		event_bus.register::<DefineTestEvent, DefineTestListener>(listener.clone());
250
251		// Emit event
252		event_bus.emit(DefineTestEvent::new(vec![1, 2, 3], "test".to_string()));
253		event_bus.wait_for_completion();
254		assert_eq!(*listener.counter.lock().unwrap(), 3);
255
256		// Emit another
257		event_bus.emit(DefineTestEvent::new(vec![1, 2, 3, 4, 5], "test2".to_string()));
258		event_bus.wait_for_completion();
259		assert_eq!(*listener.counter.lock().unwrap(), 8);
260	}
261}