pharos_server/
lifecycle.rs1use std::{future::Future, io, pin::Pin, sync::Arc};
2
3type Hook = Arc<dyn Fn() -> Pin<Box<dyn Future<Output = io::Result<()>> + Send>> + Send + Sync>;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub enum Phase {
8 Startup,
9 Started,
11 Shutdown,
12 Restart,
13 RestartFailed,
14}
15
16#[derive(Clone, Default)]
18pub struct Lifecycle {
19 hooks: Vec<(Phase, Hook)>,
20}
21
22impl Lifecycle {
23 pub fn register<F, Fut>(&mut self, phase: Phase, hook: F)
24 where
25 F: Fn() -> Fut + Send + Sync + 'static,
26 Fut: Future<Output = io::Result<()>> + Send + 'static,
27 {
28 self.hooks.push((phase, Arc::new(move || Box::pin(hook()))));
29 }
30
31 pub fn register_sync<F>(&mut self, phase: Phase, hook: F)
32 where
33 F: Fn() -> io::Result<()> + Send + Sync + 'static,
34 {
35 self.register(phase, move || std::future::ready(hook()));
36 }
37
38 pub async fn run(&self, phase: Phase) -> io::Result<()> {
39 for (_, hook) in self
40 .hooks
41 .iter()
42 .filter(|(registered, _)| *registered == phase)
43 {
44 hook().await?;
45 }
46 Ok(())
47 }
48
49 pub fn extend(&mut self, other: &Self) {
50 self.hooks.extend(other.hooks.iter().cloned());
51 }
52}
53
54impl std::fmt::Debug for Lifecycle {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 f.debug_struct("Lifecycle")
57 .field("hooks", &self.hooks.len())
58 .finish()
59 }
60}