use super::handler_group::{Group, HandlerGroup};
use crate::{Event, Handler, models::RawEvent};
use chrono::{DateTime, Utc};
use sqlx::PgTransaction;
use std::{any::Any, collections::HashMap};
pub struct EventHandlerRegistry {
handlers: HashMap<i32, Box<dyn HandlerGroup>>,
}
impl EventHandlerRegistry {
#[tracing::instrument(level = "debug")]
pub fn new() -> EventHandlerRegistry {
Self {
handlers: HashMap::new(),
}
}
#[tracing::instrument(
skip(self, handler),
fields(
event_name = E::NAME,
event_hash = E::HASH
),
level = "debug"
)]
pub fn with_handler<E, H>(&mut self, handler: H)
where
E: Event + Clone,
H: Handler<E> + 'static,
{
let group = self
.handlers
.entry(E::HASH)
.or_insert(Box::new(Group::<E>::new()));
let any_ref = group.as_mut() as &mut (dyn Any + '_);
let group = any_ref.downcast_mut::<Group<E>>().expect(
"Could not downcast to group. This indicates a hash collision between event types",
);
group.register(handler);
}
#[tracing::instrument(
skip(self, event, tx),
fields(
event_id = %event.id,
event_name = event.name,
event_hash = event.hash,
polled_at = %polled_at
)
)]
pub(crate) async fn handle<'tx>(
&'tx self,
event: &RawEvent,
polled_at: DateTime<Utc>,
tx: PgTransaction<'tx>,
) -> (PgTransaction<'tx>, Result<(), String>) {
match self.handlers.get(&event.hash) {
Some(group) => group.handle(event, polled_at, tx).await,
None => (tx, Ok(())),
}
}
}