use std::{
any::{Any, TypeId},
collections::HashMap,
};
use futures::lock::Mutex;
use once_cell::sync::Lazy;
use crate::prelude::{Actor, Address, RuntimeActorExt};
static REGISTRY: Lazy<Registry> = Lazy::new(Registry::new);
pub trait Service: Actor + Default {
const NAME: &'static str;
}
#[derive(Debug, Default)]
pub struct Registry {
services: Mutex<HashMap<&'static str, Box<dyn Any + Send>>>,
}
impl Registry {
fn new() -> Self {
Self::default()
}
pub async fn service<S: Service + Sized + 'static>() -> Address<S> {
let mut lock = REGISTRY.services.lock().await;
if let Some(maybe_addr) = lock.get(S::NAME) {
if let Some(addr) = maybe_addr.downcast_ref::<Address<S>>() {
if addr.connected() {
return addr.clone();
}
} else {
panic!(
"Two or more services have a not unique name. \
Name is {}, attempt to retrieve the type {:?}, but stored type is {:?}",
S::NAME,
TypeId::of::<Address<S>>(),
(&*maybe_addr).type_id()
);
}
}
let addr = S::default().spawn();
lock.insert(S::NAME, Box::new(addr.clone()));
addr
}
}