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}