use crate::alert::{Alert, AlertSeverity};
pub trait AlertHandler: Send {
fn on_alert(&mut self, alert: &Alert);
}
pub type AlertFilter = Box<dyn Fn(&Alert) -> bool + Send>;
struct Subscription {
handler: Box<dyn AlertHandler>,
min_severity: AlertSeverity,
source_filter: Option<String>,
}
impl Subscription {
fn matches(&self, alert: &Alert) -> bool {
if alert.severity < self.min_severity {
return false;
}
if let Some(ref src) = self.source_filter
&& alert.source != *src
{
return false;
}
true
}
}
pub struct AlertBus {
subscriptions: Vec<Subscription>,
history: Vec<Alert>,
history_limit: usize,
}
impl AlertBus {
pub fn new() -> Self {
Self::with_history_limit(1_000)
}
pub fn with_history_limit(limit: usize) -> Self {
Self {
subscriptions: Vec::new(),
history: Vec::new(),
history_limit: limit,
}
}
pub fn subscribe(
&mut self,
handler: Box<dyn AlertHandler>,
min_severity: AlertSeverity,
source: Option<String>,
) {
self.subscriptions.push(Subscription {
handler,
min_severity,
source_filter: source,
});
}
pub fn fire(&mut self, alert: Alert) {
for sub in &mut self.subscriptions {
if sub.matches(&alert) {
sub.handler.on_alert(&alert);
}
}
if self.history.len() >= self.history_limit {
self.history.remove(0);
}
self.history.push(alert);
}
pub fn history(&self) -> &[Alert] {
&self.history
}
pub fn history_at_or_above(&self, min: AlertSeverity) -> impl Iterator<Item = &Alert> {
self.history.iter().filter(move |a| a.severity >= min)
}
pub fn history_for_source<'a>(&'a self, source: &str) -> impl Iterator<Item = &'a Alert> {
self.history.iter().filter(move |a| a.source == source)
}
pub fn subscriber_count(&self) -> usize {
self.subscriptions.len()
}
}
impl Default for AlertBus {
fn default() -> Self {
Self::new()
}
}