actix_telepathy/utils/
custom_system_service.rs1use actix::{Actor, Addr, ArbiterHandle, Context, Supervisor, System, SystemService};
2use once_cell::sync::Lazy;
3use parking_lot::Mutex;
4use std::any::{Any, TypeId};
5use std::collections::HashMap;
6
7static SREG: Lazy<Mutex<HashMap<usize, PatchedSystemRegistry>>> =
8 Lazy::new(|| Mutex::new(HashMap::new()));
9
10#[derive(Debug)]
11struct PatchedSystemRegistry {
12 #[allow(dead_code)]
13 system: ArbiterHandle,
14 registry: HashMap<TypeId, Box<dyn Any + Send>>,
15}
16
17impl PatchedSystemRegistry {
18 pub(crate) fn new(system: ArbiterHandle) -> Self {
19 Self {
20 system,
21 registry: HashMap::default(),
22 }
23 }
24}
25
26pub trait CustomSystemService: Actor<Context = Context<Self>> + SystemService {
28 fn start_service_with(
30 f: impl Fn() -> Self + std::marker::Sync + 'static + std::marker::Send,
31 ) -> Addr<Self> {
32 let sys = System::current();
33 let arbiter = sys.arbiter();
34 let addr = Supervisor::start_in_arbiter(arbiter, move |ctx| {
35 let mut act = f();
36 act.custom_service_started(ctx);
37 act
38 });
39 Self::add_to_registry(addr)
40 }
41
42 #[allow(dead_code, unused_variables)]
43 fn custom_service_started(&mut self, ctx: &mut Context<Self>) {}
44
45 fn add_to_registry(addr: Addr<Self>) -> Addr<Self> {
46 let sys = System::current();
47 let mut sreg = SREG.lock();
48 let reg = sreg
49 .entry(sys.id())
50 .or_insert_with(|| PatchedSystemRegistry::new(sys.arbiter().clone()));
51 reg.registry
52 .insert(TypeId::of::<Self>(), Box::new(addr.clone()));
53 addr
54 }
55
56 fn from_custom_registry() -> Addr<Self> {
58 let sys = System::current();
59 let mut sreg = SREG.lock();
60 let reg = sreg
61 .entry(sys.id())
62 .or_insert_with(|| PatchedSystemRegistry::new(sys.arbiter().clone()));
63
64 if let Some(addr) = reg.registry.get(&TypeId::of::<Self>())
65 && let Some(addr) = addr.downcast_ref::<Addr<Self>>()
66 {
67 return addr.clone();
68 }
69
70 panic!("Please start Actor before asking for it in registry!");
71 }
72}