use crate::audit::AuditLog;
use crate::bus::CommandBus;
use crate::command::CommandRegistry;
use crate::decision::{DecisionEngine, DecisionRegistry};
use crate::error::{RuntimeError, RuntimeResult};
use crate::event::EventRegistry;
use crate::event_bus::EventBus;
use crate::identity::RuntimeIdentity;
use crate::ids::NodeId;
use crate::lifecycle::RuntimeLifecycle;
use crate::plugin::AppPlugin;
use crate::runtime::RuntimeInstance;
use crate::state::StateRegistry;
use appcore_contracts::ApplicationManifestV1;
#[derive(Debug, Default)]
pub struct RuntimeBuilder {
application_manifest: Option<ApplicationManifestV1>,
identity: Option<RuntimeIdentity>,
command_registry: CommandRegistry,
event_registry: EventRegistry,
state_registry: StateRegistry,
decision_registry: DecisionRegistry,
decision_engine: DecisionEngine,
command_bus: CommandBus,
event_bus: EventBus,
audit_log: AuditLog,
lifecycle: RuntimeLifecycle,
}
impl RuntimeBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_plugin<P: AppPlugin + ?Sized>(
&mut self,
plugin: &P,
node_id: NodeId,
) -> RuntimeResult<&mut Self> {
if self.application_manifest.is_some() {
return Err(RuntimeError::PluginAlreadyRegistered);
}
let application_manifest = plugin.application_manifest();
let identity = plugin.identity(node_id);
plugin.register_commands(&mut self.command_registry)?;
plugin.register_events(&mut self.event_registry)?;
plugin.register_states(&mut self.state_registry)?;
plugin.register_decisions(&mut self.decision_registry)?;
plugin.register_decision_nodes(&mut self.decision_engine)?;
self.sync_decision_registry_with_engine()?;
plugin.register_handlers(&mut self.command_bus)?;
self.application_manifest = Some(application_manifest);
self.identity = Some(identity);
Ok(self)
}
pub fn with_additional_plugin<P: AppPlugin + ?Sized>(
&mut self,
plugin: &P,
) -> RuntimeResult<&mut Self> {
plugin.register_commands(&mut self.command_registry)?;
plugin.register_events(&mut self.event_registry)?;
plugin.register_states(&mut self.state_registry)?;
plugin.register_decisions(&mut self.decision_registry)?;
plugin.register_decision_nodes(&mut self.decision_engine)?;
self.sync_decision_registry_with_engine()?;
plugin.register_handlers(&mut self.command_bus)?;
Ok(self)
}
fn sync_decision_registry_with_engine(&mut self) -> RuntimeResult<()> {
for name in self.decision_engine.node_names() {
if !self.decision_registry.contains(name) {
self.decision_registry.register_name(name)?;
}
}
Ok(())
}
pub fn application_manifest(&self) -> Option<&ApplicationManifestV1> {
self.application_manifest.as_ref()
}
pub fn commands(&self) -> &CommandRegistry {
&self.command_registry
}
pub fn events(&self) -> &EventRegistry {
&self.event_registry
}
pub fn states(&self) -> &StateRegistry {
&self.state_registry
}
pub fn decisions(&self) -> &DecisionRegistry {
&self.decision_registry
}
pub fn command_bus(&self) -> &CommandBus {
&self.command_bus
}
pub fn build(self) -> RuntimeResult<RuntimeInstance> {
let application_manifest = self
.application_manifest
.ok_or(RuntimeError::MissingManifest)?;
let identity = self.identity.ok_or(RuntimeError::MissingManifest)?;
Ok(RuntimeInstance {
application_manifest,
identity,
command_registry: self.command_registry,
event_registry: self.event_registry,
state_registry: self.state_registry,
decision_registry: self.decision_registry,
decision_engine: self.decision_engine,
command_bus: self.command_bus,
event_bus: self.event_bus,
audit_log: self.audit_log,
lifecycle: self.lifecycle,
})
}
}
#[cfg(test)]
mod builder_tests;