use std::collections::HashMap;
use std::fmt;
use std::sync::Arc;
use crate::context::RuntimeContext;
use crate::envelope::CommandEnvelope;
use crate::error::{RuntimeError, RuntimeResult};
use crate::handler::{CommandHandler, CommandResult};
use crate::ids::CommandName;
#[derive(Default)]
pub struct CommandBus {
handlers: HashMap<CommandName, Arc<dyn CommandHandler + Send + Sync>>,
}
impl fmt::Debug for CommandBus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CommandBus")
.field("handler_count", &self.handlers.len())
.finish()
}
}
impl CommandBus {
pub fn new() -> Self {
Self::default()
}
pub fn register_handler<H: CommandHandler + 'static>(
&mut self,
handler: H,
) -> RuntimeResult<()> {
let name = handler.command_name();
if self.handlers.contains_key(&name) {
return Err(RuntimeError::HandlerAlreadyRegistered(name));
}
self.handlers.insert(name, Arc::new(handler));
Ok(())
}
pub fn contains_handler(&self, name: &CommandName) -> bool {
self.handlers.contains_key(name)
}
pub fn len(&self) -> usize {
self.handlers.len()
}
pub fn is_empty(&self) -> bool {
self.handlers.is_empty()
}
pub fn dispatch(
&self,
command: &CommandEnvelope,
context: &dyn RuntimeContext,
) -> RuntimeResult<CommandResult> {
let name = command.command_name();
let Some(handler) = self.handlers.get(name) else {
return Err(RuntimeError::HandlerNotFound(name.clone()));
};
handler.handle(command, context)
}
}
#[cfg(test)]
#[path = "bus_tests.rs"]
mod tests;