libpetri_event/
event_store.rs1use crate::net_event::NetEvent;
2
3pub trait EventStore: Default + Send {
9 const ENABLED: bool;
10
11 fn append(&mut self, event: NetEvent);
12 fn events(&self) -> &[NetEvent];
13 fn size(&self) -> usize;
14 fn is_empty(&self) -> bool;
15}
16
17#[derive(Debug, Default)]
22pub struct NoopEventStore;
23
24impl EventStore for NoopEventStore {
25 const ENABLED: bool = false;
26
27 #[inline(always)]
28 fn append(&mut self, _event: NetEvent) {}
29
30 #[inline(always)]
31 fn events(&self) -> &[NetEvent] {
32 &[]
33 }
34
35 #[inline(always)]
36 fn size(&self) -> usize {
37 0
38 }
39
40 #[inline(always)]
41 fn is_empty(&self) -> bool {
42 true
43 }
44}
45
46#[derive(Debug, Default)]
48pub struct InMemoryEventStore {
49 events: Vec<NetEvent>,
50}
51
52impl InMemoryEventStore {
53 pub fn new() -> Self {
54 Self { events: Vec::new() }
55 }
56
57 pub fn filter(&self, predicate: impl Fn(&NetEvent) -> bool) -> Vec<&NetEvent> {
59 self.events.iter().filter(|e| predicate(e)).collect()
60 }
61
62 pub fn transition_events(&self, name: &str) -> Vec<&NetEvent> {
64 self.filter(|e| e.transition_name() == Some(name))
65 }
66
67 pub fn failures(&self) -> Vec<&NetEvent> {
69 self.filter(|e| e.is_failure())
70 }
71}
72
73impl EventStore for InMemoryEventStore {
74 const ENABLED: bool = true;
75
76 fn append(&mut self, event: NetEvent) {
77 self.events.push(event);
78 }
79
80 fn events(&self) -> &[NetEvent] {
81 &self.events
82 }
83
84 fn size(&self) -> usize {
85 self.events.len()
86 }
87
88 fn is_empty(&self) -> bool {
89 self.events.is_empty()
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 use std::sync::Arc;
97
98 #[test]
99 fn noop_store_is_always_empty() {
100 let mut store = NoopEventStore;
101 store.append(NetEvent::ExecutionStarted {
102 net_name: Arc::from("test"),
103 timestamp: 0,
104 });
105 assert!(store.is_empty());
106 assert_eq!(store.size(), 0);
107 assert!(store.events().is_empty());
108 }
109
110 #[test]
111 fn in_memory_store_records_events() {
112 let mut store = InMemoryEventStore::new();
113 store.append(NetEvent::ExecutionStarted {
114 net_name: Arc::from("test"),
115 timestamp: 0,
116 });
117 store.append(NetEvent::TransitionStarted {
118 transition_name: Arc::from("t1"),
119 timestamp: 1,
120 });
121 assert_eq!(store.size(), 2);
122 assert!(!store.is_empty());
123 }
124
125 #[test]
126 fn in_memory_store_transition_events() {
127 let mut store = InMemoryEventStore::new();
128 store.append(NetEvent::TransitionStarted {
129 transition_name: Arc::from("t1"),
130 timestamp: 1,
131 });
132 store.append(NetEvent::TransitionCompleted {
133 transition_name: Arc::from("t1"),
134 timestamp: 2,
135 });
136 store.append(NetEvent::TransitionStarted {
137 transition_name: Arc::from("t2"),
138 timestamp: 3,
139 });
140 assert_eq!(store.transition_events("t1").len(), 2);
141 assert_eq!(store.transition_events("t2").len(), 1);
142 }
143
144 #[test]
145 fn enabled_constants() {
146 const { assert!(!NoopEventStore::ENABLED) };
147 const { assert!(InMemoryEventStore::ENABLED) };
148 }
149}