use super::{emitter::EventHubEmitter, listener::Listener, registry::ListenerRegistry};
use crate::{EventEmitter, EventManager};
use anyhow::{Result, Error};
use uuid::Uuid;
use std::sync::{Arc, RwLock};
#[derive(Clone)]
pub struct EventHub<T: Clone + Send + Sync + 'static = ()> {
registry: Arc<RwLock<ListenerRegistry<T>>>,
}
impl<T: Clone + Send + Sync + 'static> EventHub<T> {
pub fn new() -> Self {
Self::default()
}
pub fn emit(&self, event_kind: &str, event_arg: T) -> Result<()> {
let listeners = self
.registry
.read()
.map_err(|err| Error::msg(format!("Mutex lock failed in event hub: {err}")))?
.listeners()
.get(event_kind)
.map(|list| list.values().cloned().collect::<Vec<_>>())
.unwrap_or_default();
let mut errors = vec![];
for listener in listeners {
if let Err(err) = listener.call(event_arg.clone()) {
errors.push(err);
}
}
if !errors.is_empty() {
return Err(Error::msg(format!(
"Failed to emit event '{event_kind}':\n{}",
errors.into_iter().map(|err| format!("\n - {err}")).collect::<String>(),
)));
}
Ok(())
}
}
impl<T: Clone + Send + Sync + 'static> Default for EventHub<T> {
fn default() -> Self {
Self {
registry: Arc::new(RwLock::new(ListenerRegistry::new())),
}
}
}
impl<T: Clone + Send + Sync + 'static> EventManager<T> for EventHub<T> {
fn list_event_kinds(&self) -> Result<Vec<String>> {
let registry = self
.registry
.read()
.map_err(|err| Error::msg(format!("Mutex lock failed in event hub: {err}")))?;
Ok(registry.listeners().keys().cloned().collect::<Vec<_>>())
}
fn has_listeners(&self, event_kind: &str) -> Result<bool> {
let registry = self
.registry
.read()
.map_err(|err| Error::msg(format!("Mutex lock failed in event hub: {err}")))?;
Ok(registry.listeners().contains_key(event_kind))
}
fn listeners_count(&self, event_kind: &str) -> Result<usize> {
let registry = self
.registry
.read()
.map_err(|err| Error::msg(format!("Mutex lock failed in event hub: {err}")))?;
Ok(registry.listeners().get(event_kind).map_or(0, |l| l.len()))
}
fn clear_listeners(&self) -> Result<()> {
let mut registry = self
.registry
.write()
.map_err(|err| Error::msg(format!("Mutex lock failed in event hub: {err}")))?;
registry.clear();
Ok(())
}
fn add_listener<F: FnMut(T) + Send + Sync + 'static>(&self, event_kind: &str, listener: F) -> Result<Uuid> {
let mut registry = self
.registry
.write()
.map_err(|err| Error::msg(format!("Mutex lock failed in event hub: {err}")))?;
Ok(registry.register_listener(event_kind, listener))
}
fn remove_listener(&self, listener_id: Uuid) -> Result<bool> {
let mut registry = self
.registry
.write()
.map_err(|err| Error::msg(format!("Mutex lock failed in event hub: {err}")))?;
Ok(registry.remove_listener(listener_id))
}
fn remove_listeners_by_kind(&self, event_kind: &str) -> Result<usize> {
let mut registry = self
.registry
.write()
.map_err(|err| Error::msg(format!("Mutex lock failed in event hub: {err}")))?;
Ok(registry.remove_listeners_by_kind(event_kind))
}
fn new_emitter(&self, event_kind: &str) -> Box<dyn EventEmitter<T>> {
let event_kind = event_kind.to_string();
let registry = Arc::clone(&self.registry);
let listener = Listener::new(move |event_arg: T| -> Result<()> {
let listeners = registry
.read()
.map_err(|err| {
let msg = format!("Mutex lock failed in event hub for kind `{event_kind}`: {err}");
Error::msg(msg)
})?
.listeners()
.get(&event_kind)
.map(|listeners| listeners.values().cloned().collect::<Vec<_>>())
.unwrap_or_default();
let mut errors = vec![];
for listener in listeners {
if let Err(err) = listener.call(event_arg.clone()) {
errors.push(err);
}
}
if !errors.is_empty() {
return Err(Error::msg(format!(
"Failed to emit event '{event_kind}':{errors}",
errors = errors.into_iter().map(|err| format!("\n - {err}")).collect::<String>(),
)));
}
Ok(())
});
Box::new(EventHubEmitter::new(listener))
}
fn new_broadcast_emitter(&self, event_kinds: &[&str]) -> Box<dyn EventEmitter<T>> {
let event_kinds = if event_kinds.is_empty() {
None
} else {
Some(event_kinds.iter().map(|&s| s.to_string()).collect::<Vec<_>>())
};
let registry = Arc::clone(&self.registry);
let listener = Listener::new(move |event_arg: T| -> Result<()> {
let (listeners, event_kinds) = {
let registry = registry.read().map_err(|err| {
let event_kinds = event_kinds.as_ref().map(|l| l.join(", ")).unwrap_or_default();
let msg = format!("Mutex lock failed in event hub for kind `{event_kinds}`: {err}");
Error::msg(msg)
})?;
let listeners = registry.listeners();
let kinds_to_process = match &event_kinds {
Some(list) => list.clone(),
None => listeners.keys().cloned().collect::<Vec<_>>(),
};
let mut event_listeners = Vec::new();
for event_kind in &kinds_to_process {
if let Some(callbacks) = listeners.get(event_kind) {
event_listeners.extend(callbacks.values().cloned());
}
}
(event_listeners, kinds_to_process.join(", "))
};
let mut errors = vec![];
for listener in listeners {
if let Err(err) = listener.call(event_arg.clone()) {
errors.push(err);
}
}
if !errors.is_empty() {
return Err(Error::msg(format!(
"Failed to emit event from hub for kinds '{event_kinds}':{errors}",
errors = errors.into_iter().map(|err| format!("\n - {err}")).collect::<String>(),
)));
}
Ok(())
});
Box::new(EventHubEmitter::new(listener))
}
fn new_null_emitter() -> Box<dyn EventEmitter<T>> {
Box::new(EventHubEmitter::new(Listener::new(|_| Ok(()))))
}
}