use crate::{Container, LifecycleRunner, Module, ModuleDefinition, ModuleGraph, Result};
pub struct Application {
container: Container,
modules: ModuleGraph,
lifecycle: LifecycleRunner,
}
impl Application {
pub fn new(container: Container, modules: ModuleGraph) -> Self {
Self {
container,
modules,
lifecycle: LifecycleRunner::empty(),
}
}
pub fn with_lifecycle(
container: Container,
modules: ModuleGraph,
lifecycle: LifecycleRunner,
) -> Self {
Self {
container,
modules,
lifecycle,
}
}
pub fn container(&self) -> &Container {
&self.container
}
pub fn modules(&self) -> &ModuleGraph {
&self.modules
}
pub async fn shutdown(&self) -> Result<()> {
self.lifecycle.shutdown().await
}
}
pub struct Nidus;
impl Nidus {
pub fn bootstrap<M: Module>() -> Result<Application> {
let graph = ModuleGraph::from_root::<M>()?;
let mut container = Container::new();
register_module_providers(&mut container, &graph)?;
Ok(Application::new(container, graph))
}
pub fn bootstrap_with_modules<M, I>(modules: I) -> Result<Application>
where
M: Module,
I: IntoIterator<Item = ModuleDefinition>,
{
let graph = ModuleGraph::from_root_and_modules::<M, I>(modules)?;
let mut container = Container::new();
register_module_providers(&mut container, &graph)?;
Ok(Application::new(container, graph))
}
pub async fn bootstrap_with_lifecycle<M: Module>(
lifecycle: LifecycleRunner,
) -> Result<Application> {
let graph = ModuleGraph::from_root::<M>()?;
let mut container = Container::new();
register_module_providers(&mut container, &graph)?;
initialize_module_providers(&mut container, &graph).await?;
lifecycle.startup().await?;
Ok(Application::with_lifecycle(container, graph, lifecycle))
}
pub async fn bootstrap_with_modules_and_lifecycle<M, I>(
modules: I,
lifecycle: LifecycleRunner,
) -> Result<Application>
where
M: Module,
I: IntoIterator<Item = ModuleDefinition>,
{
let graph = ModuleGraph::from_root_and_modules::<M, I>(modules)?;
let mut container = Container::new();
register_module_providers(&mut container, &graph)?;
initialize_module_providers(&mut container, &graph).await?;
lifecycle.startup().await?;
Ok(Application::with_lifecycle(container, graph, lifecycle))
}
}
fn register_module_providers(container: &mut Container, graph: &ModuleGraph) -> Result<()> {
for module in graph.modules() {
for registrar in module.provider_registrars() {
registrar(container)?;
}
}
Ok(())
}
async fn initialize_module_providers(container: &mut Container, graph: &ModuleGraph) -> Result<()> {
for module in graph.modules() {
for initializer in module.async_initializers() {
initializer(container).await?;
}
}
Ok(())
}