1use super::*;
2
3impl_veilid_log_facility!("registry");
4
5pub(crate) trait AsAnyArcSendSync {
6 fn as_any_arc_send_sync(self: Arc<Self>) -> Arc<dyn core::any::Any + Send + Sync>;
7}
8
9impl<T: Send + Sync + 'static> AsAnyArcSendSync for T {
10 fn as_any_arc_send_sync(self: Arc<Self>) -> Arc<dyn core::any::Any + Send + Sync> {
11 self
12 }
13}
14
15pub(crate) trait VeilidComponent:
16 AsAnyArcSendSync + VeilidComponentRegistryAccessor + core::fmt::Debug
17{
18 fn name(&self) -> &'static str;
19 fn log_facilities(&self) -> VeilidComponentLogFacilities;
20 fn init(&self) -> PinBoxFuture<'_, EyreResult<()>>;
21 fn post_init(&self) -> PinBoxFuture<'_, EyreResult<()>>;
22 fn pre_terminate(&self) -> PinBoxFuture<'_, ()>;
23 fn terminate(&self) -> PinBoxFuture<'_, ()>;
24}
25
26pub(crate) trait VeilidComponentRegistryAccessor {
27 fn registry(&self) -> VeilidComponentRegistry;
28
29 fn config(&self) -> Arc<VeilidConfig> {
30 self.registry().unlocked_inner.startup_options.config()
31 }
32 fn update_callback(&self) -> UpdateCallback {
33 self.registry()
34 .unlocked_inner
35 .startup_options
36 .update_callback()
37 }
38 fn event_bus(&self) -> EventBus {
39 self.registry().event_bus()
40 }
41 fn log_key(&self) -> VeilidLogKey {
42 self.registry().log_key()
43 }
44}
45
46pub struct VeilidComponentGuard<'a, T: Send + Sync + 'static> {
48 component: Arc<T>,
49 _phantom: core::marker::PhantomData<&'a T>,
50}
51
52impl<T> core::ops::Deref for VeilidComponentGuard<'_, T>
53where
54 T: Send + Sync + 'static,
55{
56 type Target = T;
57
58 fn deref(&self) -> &Self::Target {
59 &self.component
60 }
61}
62
63#[derive(Debug)]
64struct VeilidComponentRegistryInner {
65 type_map: HashMap<core::any::TypeId, Arc<dyn VeilidComponent + Send + Sync>>,
66 init_order: Vec<core::any::TypeId>,
67 #[cfg(any(test, feature = "test-util"))]
68 mock: bool,
69}
70
71#[derive(Debug)]
72struct VeilidComponentRegistryUnlockedInner {
73 inner: Mutex<VeilidComponentRegistryInner>,
74 startup_options: VeilidStartupOptions,
75 namespace: &'static str,
76 program_name: &'static str,
77 log_key: &'static str,
78 event_bus: EventBus,
79 init_lock: AsyncMutex<bool>,
80}
81
82#[derive(Clone, Debug)]
83pub(crate) struct VeilidComponentRegistry {
84 unlocked_inner: Arc<VeilidComponentRegistryUnlockedInner>,
85}
86
87impl VeilidComponentRegistry {
88 pub fn new(startup_options: VeilidStartupOptions) -> Self {
89 let namespace = startup_options.config().namespace.to_static_str();
90 let program_name = startup_options.config().program_name.to_static_str();
91
92 let log_key = VeilidLayerFilter::make_veilid_log_key(program_name, namespace);
93
94 Self {
95 unlocked_inner: Arc::new(VeilidComponentRegistryUnlockedInner {
96 inner: Mutex::new(VeilidComponentRegistryInner {
97 type_map: HashMap::new(),
98 init_order: Vec::new(),
99 #[cfg(any(test, feature = "test-util"))]
100 mock: false,
101 }),
102 startup_options,
103 namespace,
104 program_name,
105 log_key,
106 event_bus: EventBus::new(),
107 init_lock: AsyncMutex::new(false),
108 }),
109 }
110 }
111
112 #[cfg(any(test, feature = "test-util"))]
113 pub fn enable_mock(&self) {
114 let mut inner = self.unlocked_inner.inner.lock();
115 inner.mock = true;
116 }
117 #[expect(dead_code)]
124 pub fn namespace(&self) -> &'static str {
125 self.unlocked_inner.namespace
126 }
127
128 #[allow(dead_code)]
129 pub fn program_name(&self) -> &'static str {
130 self.unlocked_inner.program_name
131 }
132
133 pub fn log_key(&self) -> VeilidLogKey {
134 self.unlocked_inner.log_key
135 }
136
137 pub fn event_bus(&self) -> EventBus {
138 self.unlocked_inner.event_bus.clone()
139 }
140
141 pub fn register<
142 T: VeilidComponent + Send + Sync + 'static,
143 F: FnOnce(VeilidComponentRegistry) -> T,
144 >(
145 &self,
146 component_constructor: F,
147 ) {
148 let component = Arc::new(component_constructor(self.clone()));
149 let component_type_id = core::any::TypeId::of::<T>();
150
151 let mut inner = self.unlocked_inner.inner.lock();
153 if inner
154 .type_map
155 .insert(component_type_id, component)
156 .is_some()
157 {
158 veilid_log!(self error "should not register same component twice");
159 return;
160 }
161 inner.init_order.push(component_type_id);
162 }
163
164 pub fn register_with_context<
165 C,
166 T: VeilidComponent + Send + Sync + 'static,
167 F: FnOnce(VeilidComponentRegistry, C) -> T,
168 >(
169 &self,
170 component_constructor: F,
171 context: C,
172 ) {
173 let component = Arc::new(component_constructor(self.clone(), context));
174 let component_type_id = core::any::TypeId::of::<T>();
175
176 let mut inner = self.unlocked_inner.inner.lock();
178 if inner
179 .type_map
180 .insert(component_type_id, component)
181 .is_some()
182 {
183 veilid_log!(self error "should not register same component twice");
184 return;
185 }
186 inner.init_order.push(component_type_id);
187 }
188
189 pub async fn init(&self) -> EyreResult<()> {
190 let Some(mut _init_guard) = self.unlocked_inner.init_lock.try_lock() else {
191 bail!("init should only happen one at a time");
192 };
193 if *_init_guard {
194 bail!("already initialized");
195 }
196
197 VeilidLayerFilter::init_veilid_component_log_facilities(
198 self.log_key(),
199 self.get_init_order()
200 .into_iter()
201 .map(|x| x.log_facilities())
202 .collect(),
203 )?;
204
205 self.unlocked_inner.event_bus.startup()?;
207
208 let init_order = self.get_init_order();
210 let mut initialized = vec![];
211 for component in init_order {
212 if let Err(e) = component.init().await {
213 veilid_log!(self error "Error initializing component '{}': {}", component.name(), e);
214 self.terminate_inner(initialized).await;
215 self.unlocked_inner.event_bus.shutdown().await;
216 return Err(e);
217 }
218 initialized.push(component);
219 }
220
221 *_init_guard = true;
222 Ok(())
223 }
224
225 pub async fn post_init(&self) -> EyreResult<()> {
226 let Some(mut _init_guard) = self.unlocked_inner.init_lock.try_lock() else {
227 bail!("init should only happen one at a time");
228 };
229 if !*_init_guard {
230 bail!("not initialized");
231 }
232
233 let init_order = self.get_init_order();
234 let mut post_initialized = vec![];
235 for component in init_order {
236 if let Err(e) = component.post_init().await {
237 self.pre_terminate_inner(post_initialized).await;
238 return Err(e);
239 }
240 post_initialized.push(component)
241 }
242 Ok(())
243 }
244
245 pub async fn pre_terminate(&self) {
246 let Some(mut _init_guard) = self.unlocked_inner.init_lock.try_lock() else {
247 veilid_log!(self error "terminate should only happen one at a time");
248 return;
249 };
250 if !*_init_guard {
251 veilid_log!(self error "not initialized");
252 return;
253 }
254
255 let init_order = self.get_init_order();
256 self.pre_terminate_inner(init_order).await;
257 }
258
259 pub async fn terminate(&self) {
260 let Some(mut _init_guard) = self.unlocked_inner.init_lock.try_lock() else {
261 veilid_log!(self error "terminate should only happen one at a time");
262 return;
263 };
264 if !*_init_guard {
265 veilid_log!(self error "not initialized");
266 return;
267 }
268
269 let init_order = self.get_init_order();
271 self.terminate_inner(init_order).await;
272
273 self.unlocked_inner.event_bus.shutdown().await;
275
276 if let Err(e) = VeilidLayerFilter::terminate_veilid_component_log_facilities(self.log_key())
278 {
279 eprintln!("Error terminating log facilities: {}", e);
280 }
281
282 *_init_guard = false;
283 }
284
285 async fn pre_terminate_inner(
286 &self,
287 pre_initialized: Vec<Arc<dyn VeilidComponent + Send + Sync>>,
288 ) {
289 for component in pre_initialized.iter().rev() {
290 component.pre_terminate().await;
291 }
292 }
293 async fn terminate_inner(&self, initialized: Vec<Arc<dyn VeilidComponent + Send + Sync>>) {
294 for component in initialized.iter().rev() {
295 let refs = Arc::strong_count(component);
296 if refs > 2 {
297 veilid_log!(self warn
298 "Terminating component '{}' while still referenced ({} extra references)",
299 component.name(),
300 refs - 2
301 );
302 }
303 component.terminate().await;
304 }
305 }
306
307 fn get_init_order(&self) -> Vec<Arc<dyn VeilidComponent + Send + Sync>> {
308 let inner = self.unlocked_inner.inner.lock();
309 inner
310 .init_order
311 .iter()
312 .map(|id| inner.type_map.get(id).unwrap_or_log().clone())
313 .collect::<Vec<_>>()
314 }
315
316 pub fn lookup<'a, T: VeilidComponent + Send + Sync + 'static>(
319 &self,
320 ) -> Option<VeilidComponentGuard<'a, T>> {
321 let inner = self.unlocked_inner.inner.lock();
322 let component_type_id = core::any::TypeId::of::<T>();
323 let component_dyn = inner.type_map.get(&component_type_id)?.clone();
324 let component = component_dyn
325 .as_any_arc_send_sync()
326 .downcast::<T>()
327 .unwrap_or_log();
328 Some(VeilidComponentGuard {
329 component,
330 _phantom: core::marker::PhantomData {},
331 })
332 }
333}
334
335impl VeilidComponentRegistryAccessor for VeilidComponentRegistry {
336 fn registry(&self) -> VeilidComponentRegistry {
337 self.clone()
338 }
339}
340
341impl VeilidComponentRegistryAccessor for &VeilidComponentRegistry {
342 fn registry(&self) -> VeilidComponentRegistry {
343 (*self).clone()
344 }
345}
346
347macro_rules! impl_veilid_component_accessors {
350 ($struct_name:ty) => {
351 impl VeilidComponentRegistryAccessor for $struct_name {
352 fn registry(&self) -> VeilidComponentRegistry {
353 self.registry.clone()
354 }
355 }
356 impl VeilidComponentRegistryAccessor for &$struct_name {
357 fn registry(&self) -> VeilidComponentRegistry {
358 self.registry.clone()
359 }
360 }
361 };
362}
363
364pub(crate) use impl_veilid_component_accessors;
365
366macro_rules! impl_veilid_component {
369 ($component_name:ty) => {
370 impl_veilid_component_accessors!($component_name);
371
372 impl VeilidComponent for $component_name {
373 fn name(&self) -> &'static str {
374 stringify!($component_name)
375 }
376
377 fn log_facilities(&self) -> VeilidComponentLogFacilities {
378 <$component_name>::log_facilities_impl(self)
379 }
380
381 fn init(&self) -> PinBoxFuture<'_, EyreResult<()>> {
382 Box::pin(async { self.init_async().await })
383 }
384
385 fn post_init(&self) -> PinBoxFuture<'_, EyreResult<()>> {
386 Box::pin(async { self.post_init_async().await })
387 }
388
389 fn pre_terminate(&self) -> PinBoxFuture<'_, ()> {
390 Box::pin(async { self.pre_terminate_async().await })
391 }
392
393 fn terminate(&self) -> PinBoxFuture<'_, ()> {
394 Box::pin(async { self.terminate_async().await })
395 }
396 }
397 };
398}
399
400pub(crate) use impl_veilid_component;
401
402macro_rules! impl_setup_task {
408 ($this:expr, $this_type:ty, $task_name:ident, $task_routine:ident ) => {{
409 let registry = $this.registry();
410 $this.$task_name.set_routine(move |s, l, t| {
411 let registry = registry.clone();
412 Box::pin(async move {
413 let this = registry.lookup::<$this_type>().unwrap_or_log();
414 this.$task_routine(s, Timestamp::new(l), Timestamp::new(t))
415 })
416 });
417 }};
418}
419
420pub(crate) use impl_setup_task;
421
422macro_rules! impl_setup_task_clone {
423 ($this:expr, $task_name:ident, $task_routine:ident ) => {{
424 let this = $this.clone();
425 $this.$task_name.set_routine(move |s, l, t| {
426 let this = this.clone();
427 Box::pin(async move { this.$task_routine(s, Timestamp::new(l), Timestamp::new(t)) })
428 });
429 }};
430}
431
432pub(crate) use impl_setup_task_clone;
433
434macro_rules! impl_setup_task_async {
435 ($this:expr, $this_type:ty, $task_name:ident, $task_routine:ident ) => {{
436 let registry = $this.registry();
437 $this.$task_name.set_routine(move |s, l, t| {
438 let registry = registry.clone();
439 Box::pin(async move {
440 let this = registry.lookup::<$this_type>().unwrap_or_log();
441 this.$task_routine(s, Timestamp::new(l), Timestamp::new(t))
442 .await
443 })
444 });
445 }};
446}
447
448pub(crate) use impl_setup_task_async;
449
450macro_rules! impl_setup_task_async_clone {
451 ($this:expr, $task_name:ident, $task_routine:ident ) => {{
452 let this = $this.clone();
453 $this.$task_name.set_routine(move |s, l, t| {
454 let this = this.clone();
455 Box::pin(async move {
456 this.$task_routine(s, Timestamp::new(l), Timestamp::new(t))
457 .await
458 })
459 });
460 }};
461}
462
463pub(crate) use impl_setup_task_async_clone;
464
465macro_rules! impl_subscribe_event_bus {
469 ($this:expr, $this_type:ty, $event_handler:ident ) => {{
470 let registry = $this.registry();
471 $this.event_bus().subscribe(move |evt| {
472 let registry = registry.clone();
473 Box::pin(async move {
474 let this = registry.lookup::<$this_type>().unwrap_or_log();
475 this.$event_handler(evt);
476 })
477 })
478 }};
479}
480
481pub(crate) use impl_subscribe_event_bus;
482
483macro_rules! impl_subscribe_event_bus_async {
484 ($this:expr, $this_type:ty, $event_handler:ident ) => {{
485 let registry = $this.registry();
486 $this.event_bus().subscribe(move |evt| {
487 let registry = registry.clone();
488 Box::pin(async move {
489 let this = registry.lookup::<$this_type>().unwrap_or_log();
490 this.$event_handler(evt).await;
491 })
492 })
493 }};
494}
495
496pub(crate) use impl_subscribe_event_bus_async;
497
498macro_rules! impl_subscribe_event_bus_async_clone {
499 ($this:expr, $event_handler:ident ) => {{
500 let this = $this.clone();
501 $this.event_bus().subscribe(move |evt| {
502 let this = this.clone();
503 Box::pin(async move {
504 this.$event_handler(evt).await;
505 })
506 })
507 }};
508}
509
510pub(crate) use impl_subscribe_event_bus_async_clone;
511
512macro_rules! impl_subscribe_event_bus_clone {
513 ($this:expr, $event_handler:ident ) => {{
514 let this = $this.clone();
515 $this.event_bus().subscribe(move |evt| {
516 let this = this.clone();
517 Box::pin(async move {
518 this.$event_handler(evt);
519 })
520 })
521 }};
522}
523
524pub(crate) use impl_subscribe_event_bus_clone;