jupiter/
builder.rs

1//! Provides a builder which can be used to setup and initialize the framework.
2//!
3//! This can be used to crate and setup central parts of the framework. As Jupiter provides some
4//! optional modules, a builder permits to selectively enable or disable them.
5//!
6//! # Example
7//! Setting up the framework with all features enabled:
8//! ```no_run
9//! # use jupiter::builder::Builder;
10//! # use jupiter::server::Server;
11//! #[tokio::main]
12//! async fn main() {
13//!     // Enable all features and build the platform...
14//!     let platform = Builder::new().enable_all().build().await;
15//!
16//!     // Register custom functions here...
17//!
18//!     // Start the main event loop of the server...
19//!     platform.require::<Server>().event_loop().await;
20//! }
21//! ```
22use crate::platform::Platform;
23use crate::server::Server;
24use crate::{init_logging, JUPITER_REVISION, JUPITER_VERSION};
25use std::sync::Arc;
26
27/// Initializes the framework by creating and initializing all core components.
28///
29/// As Jupiter provides a bunch of components of which some are optional, the actual setup
30/// can be configured here.
31///
32/// # Example
33/// Setting up the framework with all features enabled:
34/// ```no_run
35/// # use jupiter::builder::Builder;
36/// # use jupiter::server::Server;
37/// #[tokio::main]
38/// async fn main() {
39///     // Enable all features and build the platform...
40///     let platform = Builder::new().enable_all().build().await;
41///
42///     // Register custom functions here...
43///     
44///     // Start the main event loop of the server...
45///     platform.require::<Server>().event_loop().await;
46/// }
47/// ```
48#[derive(Default)]
49pub struct Builder {
50    setup_logging: bool,
51    enable_signals: bool,
52    core_commands: bool,
53    setup_config: bool,
54    setup_commands: bool,
55    setup_server: bool,
56    version_info: String,
57    revision_info: String,
58}
59
60impl Builder {
61    /// Creates a new builder.
62    pub fn new() -> Self {
63        Builder {
64            setup_logging: false,
65            enable_signals: false,
66            core_commands: false,
67            setup_config: false,
68            setup_commands: false,
69            setup_server: false,
70            version_info: "-".to_string(),
71            revision_info: "-".to_string(),
72        }
73    }
74
75    /// Enables all features.
76    ///
77    /// Note that using this method (and then maybe disabling selected components) is quote
78    /// convenient, but be aware that new components which might be added in a library update
79    /// will then also be enabled by default. This might or might not be the expected behaviour.
80    pub fn enable_all(mut self) -> Self {
81        self.setup_logging = true;
82        self.enable_signals = true;
83        self.core_commands = true;
84        self.setup_config = true;
85        self.setup_commands = true;
86        self.setup_server = true;
87
88        self
89    }
90
91    /// Enables the automatic setup of the logging system.
92    ///
93    /// Using this, we properly initialize **simplelog** to log to stdout. As we intend Jupiter
94    /// to be run in docker containers, this is all that is needed for proper logging. The date
95    /// format being used is digestible by established tools like **greylog**.
96    pub fn enable_logging(mut self) -> Self {
97        self.setup_logging = true;
98        self
99    }
100
101    /// Disables the automatic setup of the logging system after [enable_all()](Builder::enable_all)
102    /// has been used.
103    pub fn disable_logging(mut self) -> Self {
104        self.setup_logging = false;
105        self
106    }
107
108    /// Installs a signal listener which terminates the framework once **CTRL-C** or **SIGHUP**
109    /// is received.
110    ///
111    /// For more details see: [signals](crate::signals)
112    pub fn enable_signals(mut self) -> Self {
113        self.enable_signals = true;
114        self
115    }
116
117    /// Disables installing the signal listener after [enable_all()](Builder::enable_all)
118    /// has been used.
119    pub fn disable_signals(mut self) -> Self {
120        self.enable_signals = false;
121        self
122    }
123
124    /// Installs a bunch of health and maintenance commands.
125    ///
126    /// For more details see: [core](crate::core)
127    pub fn enable_core_commands(mut self) -> Self {
128        self.core_commands = true;
129        self
130    }
131
132    /// Disables installing the **core** commands after [enable_all()](Builder::enable_all)
133    /// has been used.
134    pub fn disable_core_commands(mut self) -> Self {
135        self.core_commands = false;
136        self
137    }
138
139    /// Installs [config::Config](jupiter::config::Config) and loads the **settings.yml**.
140    ///
141    /// For more details see: [config](crate::config)
142    pub fn enable_config(mut self) -> Self {
143        self.setup_config = true;
144        self
145    }
146
147    /// Disables setting up a **Config** instance after [enable_all()](Builder::enable_all)
148    /// has been used.
149    pub fn disable_config(mut self) -> Self {
150        self.setup_config = false;
151        self
152    }
153
154    /// Creates and installs a [CommandDictionary](crate::commands::CommandDictionary).
155    ///
156    /// For more details see: [Commands](crate::commands)
157    pub fn enable_commands(mut self) -> Self {
158        self.setup_commands = true;
159        self
160    }
161
162    /// Disables setting up a **Commands** instance after [enable_all()](Builder::enable_all)
163    /// has been used.
164    pub fn disable_commands(mut self) -> Self {
165        self.setup_commands = false;
166        self
167    }
168
169    /// Creates and installs a [Server](crate::server::Server) instance.
170    ///
171    /// For more details see: [server](crate::server::Server). Note that still, the main event loop
172    /// has to be invoked manually via: `platform.require::<Server>().event_loop().await`.
173    pub fn enable_server(mut self) -> Self {
174        self.setup_server = true;
175        self
176    }
177
178    /// Disables setting up a **Server** instance after [enable_all()](Builder::enable_all)
179    /// has been used.
180    pub fn disable_server(mut self) -> Self {
181        self.setup_server = false;
182        self
183    }
184
185    /// Specifies the version of the application to show when calling `SYS.VERSION`.
186    pub fn with_version(mut self, version: impl AsRef<str>, revision: impl AsRef<str>) -> Self {
187        self.version_info = version.as_ref().to_string();
188        self.revision_info = revision.as_ref().to_string();
189
190        self
191    }
192
193    /// Builds the [Platform](jupiter::platform::Platform) registry with all the enabled components
194    /// being registered.
195    pub async fn build(self) -> Arc<Platform> {
196        let platform = Platform::new();
197
198        if self.setup_logging {
199            init_logging();
200        }
201
202        log::info!(
203            "||. JUPITER (v {} - rev {}) running on {} core(s) in {} CPU(s)",
204            JUPITER_VERSION,
205            JUPITER_REVISION,
206            num_cpus::get(),
207            num_cpus::get_physical()
208        );
209
210        if self.enable_signals {
211            crate::signals::install(platform.clone());
212        }
213
214        if self.setup_config {
215            let _ = crate::config::install(platform.clone(), true).await;
216        }
217
218        if self.setup_server {
219            let _ = Server::install(&platform);
220        }
221
222        if self.setup_commands {
223            let _ = crate::commands::CommandDictionary::install(&platform);
224
225            if self.core_commands {
226                crate::core::install(platform.clone(), self.version_info, self.revision_info);
227            }
228        }
229
230        platform
231    }
232}