1use 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}