1use crate::alert::{Alert, AlertSeverity};
2
3pub trait AlertHandler: Send {
5 fn on_alert(&mut self, alert: &Alert);
7}
8
9pub type AlertFilter = Box<dyn Fn(&Alert) -> bool + Send>;
11
12struct Subscription {
13 handler: Box<dyn AlertHandler>,
14 min_severity: AlertSeverity,
15 source_filter: Option<String>,
16}
17
18impl Subscription {
19 fn matches(&self, alert: &Alert) -> bool {
20 if alert.severity < self.min_severity {
21 return false;
22 }
23 if let Some(ref src) = self.source_filter
24 && alert.source != *src
25 {
26 return false;
27 }
28 true
29 }
30}
31
32pub struct AlertBus {
44 subscriptions: Vec<Subscription>,
45 history: Vec<Alert>,
47 history_limit: usize,
48}
49
50impl AlertBus {
51 pub fn new() -> Self {
53 Self::with_history_limit(1_000)
54 }
55
56 pub fn with_history_limit(limit: usize) -> Self {
57 Self {
58 subscriptions: Vec::new(),
59 history: Vec::new(),
60 history_limit: limit,
61 }
62 }
63
64 pub fn subscribe(
67 &mut self,
68 handler: Box<dyn AlertHandler>,
69 min_severity: AlertSeverity,
70 source: Option<String>,
71 ) {
72 self.subscriptions.push(Subscription {
73 handler,
74 min_severity,
75 source_filter: source,
76 });
77 }
78
79 pub fn fire(&mut self, alert: Alert) {
81 for sub in &mut self.subscriptions {
82 if sub.matches(&alert) {
83 sub.handler.on_alert(&alert);
84 }
85 }
86 if self.history.len() >= self.history_limit {
87 self.history.remove(0);
88 }
89 self.history.push(alert);
90 }
91
92 pub fn history(&self) -> &[Alert] {
94 &self.history
95 }
96
97 pub fn history_at_or_above(&self, min: AlertSeverity) -> impl Iterator<Item = &Alert> {
99 self.history.iter().filter(move |a| a.severity >= min)
100 }
101
102 pub fn history_for_source<'a>(&'a self, source: &str) -> impl Iterator<Item = &'a Alert> {
104 self.history.iter().filter(move |a| a.source == source)
105 }
106
107 pub fn subscriber_count(&self) -> usize {
108 self.subscriptions.len()
109 }
110}
111
112impl Default for AlertBus {
113 fn default() -> Self {
114 Self::new()
115 }
116}