xtra_addons/
registry.rs

1use futures::lock::Mutex;
2use once_cell::sync::OnceCell;
3use std::any::{Any, TypeId};
4use std::collections::HashMap;
5use xtra::prelude::*;
6use xtra::spawn::AsyncStd;
7
8static GLOBAL_REGISTRY: OnceCell<Mutex<HashMap<TypeId, Box<dyn Any + Send>>>> = OnceCell::new();
9
10pub struct Registry;
11
12impl Registry {
13    pub async fn get<A: Actor>() -> Option<Address<A>> {
14        let registry = GLOBAL_REGISTRY.get_or_init(Default::default);
15        let registry = registry.lock().await;
16
17        registry
18            .get(&TypeId::of::<A>())
19            .map(|addr| addr.downcast_ref::<Address<A>>().unwrap().clone())
20    }
21
22    pub async fn get_or_create_default<A: Actor + Default>() -> Address<A> {
23        let registry = GLOBAL_REGISTRY.get_or_init(Default::default);
24        let mut registry = registry.lock().await;
25
26        match registry.get_mut(&TypeId::of::<A>()) {
27            Some(addr) => addr.downcast_ref::<Address<A>>().unwrap().clone(),
28            None => {
29                let actor_manager = A::default().create(None);
30                let addr = actor_manager.spawn(&mut AsyncStd);
31                registry.insert(TypeId::of::<Self>(), Box::new(addr.clone()));
32                addr
33            }
34        }
35    }
36
37    pub async fn register<A: Actor>(addr: Address<A>) -> Result<(), &'static str> {
38        let registry = GLOBAL_REGISTRY.get_or_init(Default::default);
39        let mut registry = registry.lock().await;
40
41        match registry.get_mut(&TypeId::of::<A>()) {
42            Some(_) => Err("Duplicate entry"),
43            None => {
44                registry.insert(TypeId::of::<A>(), Box::new(addr));
45                Ok(())
46            }
47        }
48    }
49}