registry/
registry.rs

1use std::time::Duration;
2
3use serde::Deserialize;
4use serde::Serialize;
5
6use hydra::Application;
7use hydra::ChildSpec;
8use hydra::ExitReason;
9use hydra::GenServer;
10use hydra::GenServerOptions;
11use hydra::Pid;
12use hydra::Process;
13use hydra::ProcessFlags;
14use hydra::Registry;
15use hydra::RegistryKey;
16use hydra::RegistryOptions;
17use hydra::Shutdown;
18use hydra::SupervisionStrategy;
19use hydra::Supervisor;
20use hydra::SupervisorOptions;
21
22async fn test_registry() {
23    Registry::start_process("space-registry", "my awesome space id", None)
24        .await
25        .expect("Failed to start process");
26
27    Registry::start_process("space-registry", "my lame space id", None)
28        .await
29        .expect("Failed to start process");
30
31    let pid = Registry::lookup("space-registry", "my awesome space id", None)
32        .await
33        .expect("Failed to lookup process");
34
35    tracing::info!("Looked up space process: {:?}", pid);
36
37    let count = Registry::count("space-registry", None)
38        .await
39        .expect("Failed to count processes");
40
41    tracing::info!("Count of registered processes: {:?}", count);
42
43    let list = Registry::list("space-registry", None)
44        .await
45        .expect("Failed to list processes");
46
47    tracing::info!("List of registered processes: {:?}", list);
48}
49
50#[derive(Debug, Serialize, Deserialize)]
51enum MyMessage {
52    // No messages used.
53}
54
55struct MyApplication;
56
57impl Application for MyApplication {
58    async fn start(&self) -> Result<Pid, ExitReason> {
59        // Spawn a registry that will take care of registering 'MySpace'.
60        let children = [
61            Registry::new("space-registry")
62                .with_start(|key| {
63                    let RegistryKey::String(id) = key else {
64                        panic!()
65                    };
66
67                    MySpace::new(id).start_link(GenServerOptions::new())
68                })
69                .with_shutdown(Shutdown::Infinity)
70                .child_spec(RegistryOptions::new())
71                .id("space-registry"),
72            ChildSpec::new("test-registry")
73                .start(move || async { Ok(Process::spawn(test_registry())) }),
74        ];
75
76        // Restart only the terminated child.
77        Supervisor::with_children(children)
78            .strategy(SupervisionStrategy::OneForOne)
79            .start_link(SupervisorOptions::new())
80            .await
81    }
82}
83
84#[derive(Clone)]
85struct MySpace {
86    id: String,
87}
88
89impl MySpace {
90    /// Constructs a new [MySpace].
91    pub fn new(id: String) -> Self {
92        Self { id }
93    }
94}
95
96impl GenServer for MySpace {
97    type Message = MyMessage;
98
99    async fn init(&mut self) -> Result<(), ExitReason> {
100        Process::set_flags(ProcessFlags::TRAP_EXIT);
101
102        tracing::info!("Init MySpace for {:?}", self.id);
103
104        Ok(())
105    }
106
107    async fn terminate(&mut self, _reason: ExitReason) {
108        tracing::info!("Shutting down MySpace! {:?}", self.id);
109
110        Process::sleep(Duration::from_secs(5)).await;
111    }
112}
113
114fn main() {
115    // This method will only return once the supervisor linked in `start` has terminated.
116    Application::run(MyApplication)
117}