use std::any::TypeId;
use std::collections::HashMap;
use std::fmt::Debug;
use std::fmt::Formatter;
use std::fmt::Result as FormatterResult;
use std::sync::Arc;
use crate::command::Command;
use crate::command::CommandHandler;
use crate::query::Query;
use crate::query::QueryHandler;
use crate::registry::executor::CommandHandlerWrapper;
use crate::registry::executor::QueryHandlerWrapper;
#[derive(Default)]
pub struct CommandHandlerRegistry {
#[doc(hidden)]
pub(crate) handlers: HashMap<TypeId, Arc<dyn CommandHandlerWrapper>>,
}
#[derive(Default)]
pub struct QueryHandlerRegistry {
#[doc(hidden)]
pub(crate) handlers: HashMap<TypeId, Arc<dyn QueryHandlerWrapper>>,
}
impl CommandHandlerRegistry {
pub fn new() -> Self {
Self {
handlers: HashMap::new(),
}
}
pub fn register<C: Command>(&mut self, handler: impl CommandHandler<C> + 'static) {
self.handlers.insert(
TypeId::of::<C>(),
Arc::new(Box::new(handler) as Box<dyn CommandHandler<C>>),
);
}
pub fn get_handler<C: Command>(&self) -> Option<Box<dyn CommandHandler<C>>> {
self.handlers
.get(&TypeId::of::<C>())
.cloned()
.map(|handler| Box::new(handler) as Box<dyn CommandHandler<C>>)
}
}
impl QueryHandlerRegistry {
pub fn new() -> Self {
Self {
handlers: HashMap::new(),
}
}
pub fn register<Q: Query>(&mut self, handler: impl QueryHandler<Q> + 'static) {
self.handlers.insert(
TypeId::of::<Q>(),
Arc::new(Box::new(handler) as Box<dyn QueryHandler<Q>>),
);
}
pub fn get_handler<Q: Query>(&self) -> Option<Box<dyn QueryHandler<Q>>> {
self.handlers
.get(&TypeId::of::<Q>())
.cloned()
.map(|handler| Box::new(handler) as Box<dyn QueryHandler<Q>>)
}
}
impl Debug for CommandHandlerRegistry {
fn fmt(&self, f: &mut Formatter<'_>) -> FormatterResult {
f.debug_struct("CommandHandlerRegistry").finish()
}
}
impl Debug for QueryHandlerRegistry {
fn fmt(&self, f: &mut Formatter<'_>) -> FormatterResult {
f.debug_struct("QueryHandlerRegistry").finish()
}
}
#[doc(hidden)]
mod executor {
use std::any::Any;
use std::sync::Arc;
use crate::async_trait;
use crate::command::Command;
use crate::command::CommandHandler;
use crate::query::Query;
use crate::query::QueryHandler;
#[async_trait]
pub trait CommandHandlerWrapper: Send + Sync {
async fn execute(&self, command: Box<dyn Any + Send>) -> Box<dyn Any + Send>;
}
#[async_trait]
pub trait QueryHandlerWrapper: Send + Sync {
async fn execute(&self, query: Box<dyn Any + Send>) -> Box<dyn Any + Send>;
}
#[async_trait]
impl<C: Command> CommandHandlerWrapper for Box<dyn CommandHandler<C>> {
async fn execute(&self, command: Box<dyn Any + Send>) -> Box<dyn Any + Send> {
let command = *command.downcast::<C>().unwrap();
let result = self.handle(command).await;
Box::new(result) as Box<dyn Any + Send>
}
}
#[async_trait]
impl<Q: Query> QueryHandlerWrapper for Box<dyn QueryHandler<Q>> {
async fn execute(&self, query: Box<dyn Any + Send>) -> Box<dyn Any + Send> {
let result = self.handle(*query.downcast::<Q>().unwrap()).await;
Box::new(result) as Box<dyn Any + Send>
}
}
#[async_trait]
impl<C: Command> CommandHandler<C> for Arc<dyn CommandHandlerWrapper> {
async fn handle(&self, command: C) -> Result<C::Metadata, C::Error> {
let result = self.execute(Box::new(command)).await;
*result.downcast().unwrap()
}
}
#[async_trait]
impl<Q: Query> QueryHandler<Q> for Arc<dyn QueryHandlerWrapper> {
async fn handle(&self, query: Q) -> Result<Q::Output, Q::Error> {
let result = self.execute(Box::new(query)).await;
*result.downcast().unwrap()
}
}
}