Skip to main content

atomr_hosting/
lib.rs

1//! atomr-hosting.
2//!
3//! Builder for wiring together `ActorSystem`, config, and DI container.
4
5use std::sync::Arc;
6
7use atomr_config::Config;
8use atomr_core::actor::ActorSystem;
9use atomr_di::ServiceContainer;
10
11type SetupHook = Box<dyn FnOnce(&ActorSystem) + Send + 'static>;
12
13pub struct ActorSystemBuilder {
14    name: String,
15    config: Option<Config>,
16    container: Arc<ServiceContainer>,
17    setup_hooks: Vec<SetupHook>,
18}
19
20impl ActorSystemBuilder {
21    pub fn new(name: impl Into<String>) -> Self {
22        Self {
23            name: name.into(),
24            config: None,
25            container: Arc::new(ServiceContainer::new()),
26            setup_hooks: Vec::new(),
27        }
28    }
29
30    pub fn with_config(mut self, config: Config) -> Self {
31        self.config = Some(config);
32        self
33    }
34
35    pub fn with_services<F>(self, f: F) -> Self
36    where
37        F: FnOnce(&ServiceContainer),
38    {
39        f(&self.container);
40        self
41    }
42
43    pub fn on_start<F>(mut self, f: F) -> Self
44    where
45        F: FnOnce(&ActorSystem) + Send + 'static,
46    {
47        self.setup_hooks.push(Box::new(f));
48        self
49    }
50
51    pub async fn build(self) -> Result<HostedActorSystem, Box<dyn std::error::Error>> {
52        let config = self.config.unwrap_or_else(Config::empty);
53        let system = ActorSystem::create(self.name, config).await?;
54        for hook in self.setup_hooks {
55            hook(&system);
56        }
57        Ok(HostedActorSystem { system, container: self.container })
58    }
59}
60
61pub struct HostedActorSystem {
62    pub system: ActorSystem,
63    pub container: Arc<ServiceContainer>,
64}
65
66impl HostedActorSystem {
67    pub async fn terminate(&self) {
68        self.system.terminate().await;
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[tokio::test]
77    async fn builder_constructs_system() {
78        let hosted = ActorSystemBuilder::new("hosted").build().await.unwrap();
79        hosted.terminate().await;
80    }
81}