///|
/// Event persisted by the in-memory store.
pub(all) struct StoredEvent {
sequence : Int
event : Event
source : String
stored_tick : Int
} derive(Eq, Debug)
///|
/// Query criteria. Empty strings disable the corresponding filter.
pub(all) struct EventQuery {
name : String
topic_pattern : String
tag : String
correlation_id : String
min_priority : Int
after_sequence : Int
limit : Int
} derive(Eq, Debug)
///|
pub(all) struct EventStore {
records : Array[StoredEvent]
next_sequence : Int
max_entries : Int
} derive(Eq, Debug)
///|
pub(all) struct StoreStats {
entries : Int
first_sequence : Int
last_sequence : Int
next_sequence : Int
} derive(Eq, Debug)
///|
pub fn EventQuery::all() -> EventQuery {
{
name: "",
topic_pattern: "",
tag: "",
correlation_id: "",
min_priority: 0,
after_sequence: -1,
limit: 0,
}
}
///|
pub fn EventQuery::with_name(self : EventQuery, name : String) -> EventQuery {
{ ..self, name, }
}
///|
pub fn EventQuery::with_topic(
self : EventQuery,
topic_pattern : String,
) -> EventQuery {
{ ..self, topic_pattern, }
}
///|
pub fn EventQuery::with_tag(self : EventQuery, tag : String) -> EventQuery {
{ ..self, tag, }
}
///|
pub fn EventQuery::with_correlation(
self : EventQuery,
correlation_id : String,
) -> EventQuery {
{ ..self, correlation_id, }
}
///|
pub fn EventQuery::with_min_priority(
self : EventQuery,
min_priority : Int,
) -> EventQuery {
{ ..self, min_priority, }
}
///|
pub fn EventQuery::after(self : EventQuery, after_sequence : Int) -> EventQuery {
{ ..self, after_sequence, }
}
///|
pub fn EventQuery::take(self : EventQuery, limit : Int) -> EventQuery {
{ ..self, limit, }
}
///|
pub fn EventQuery::matches(self : EventQuery, record : StoredEvent) -> Bool {
if record.sequence <= self.after_sequence {
return false
}
if self.name != "" && record.event.name != self.name {
return false
}
if !topic_matches(self.topic_pattern, record.event.topic) {
return false
}
if self.tag != "" && !record.event.has_tag(self.tag) {
return false
}
if self.correlation_id != "" &&
record.event.correlation_id != self.correlation_id {
return false
}
record.event.priority >= self.min_priority
}
///|
pub fn EventStore::new(max_entries? : Int = 0) -> EventStore {
{ records: [], next_sequence: 1, max_entries }
}
///|
fn trim_records(
records : Array[StoredEvent],
max_entries : Int,
) -> Array[StoredEvent] {
if max_entries <= 0 || records.length() <= max_entries {
return records
}
let kept : Array[StoredEvent] = []
let skip = records.length() - max_entries
let mut index = 0
for record in records {
if index >= skip {
kept.push(record)
}
index = index + 1
}
kept
}
///|
pub fn EventStore::append(
self : EventStore,
event : Event,
source? : String = "",
stored_tick? : Int = 0,
) -> (EventStore, StoredEvent) {
let record = { sequence: self.next_sequence, event, source, stored_tick }
let records : Array[StoredEvent] = []
for old in self.records {
records.push(old)
}
records.push(record)
(
{
records: trim_records(records, self.max_entries),
next_sequence: self.next_sequence + 1,
max_entries: self.max_entries,
},
record,
)
}
///|
pub fn EventStore::append_many(
self : EventStore,
events : Array[Event],
source? : String = "",
stored_tick? : Int = 0,
) -> (EventStore, Array[StoredEvent]) {
let added : Array[StoredEvent] = []
let mut store = self
for event in events {
let (next, record) = store.append(event, source~, stored_tick~)
store = next
added.push(record)
}
(store, added)
}
///|
pub fn EventStore::length(self : EventStore) -> Int {
self.records.length()
}
///|
pub fn EventStore::is_empty(self : EventStore) -> Bool {
self.records.length() == 0
}
///|
pub fn EventStore::query(
self : EventStore,
query : EventQuery,
) -> Array[StoredEvent] {
let result : Array[StoredEvent] = []
for record in self.records {
if query.matches(record) &&
(query.limit <= 0 || result.length() < query.limit) {
result.push(record)
}
}
result
}
///|
pub fn EventStore::get(self : EventStore, sequence : Int) -> StoredEvent? {
for record in self.records {
if record.sequence == sequence {
return Some(record)
}
}
None
}
///|
pub fn EventStore::latest(self : EventStore) -> StoredEvent? {
if self.records.length() == 0 {
None
} else {
self.records.get(self.records.length() - 1)
}
}
///|
pub fn EventStore::events(self : EventStore) -> Array[Event] {
let events : Array[Event] = []
for record in self.records {
events.push(record.event)
}
events
}
///|
pub fn EventStore::remove_before(
self : EventStore,
sequence : Int,
) -> EventStore {
let records : Array[StoredEvent] = []
for record in self.records {
if record.sequence >= sequence {
records.push(record)
}
}
{ ..self, records, }
}
///|
pub fn EventStore::clear(self : EventStore) -> EventStore {
{ ..self, records: [] }
}
///|
pub fn EventStore::stats(self : EventStore) -> StoreStats {
let mut first = 0
let mut last = 0
match self.records.get(0) {
Some(record) => first = record.sequence
None => ()
}
match self.latest() {
Some(record) => last = record.sequence
None => ()
}
{
entries: self.records.length(),
first_sequence: first,
last_sequence: last,
next_sequence: self.next_sequence,
}
}
///|
pub fn EventStore::replay(
self : EventStore,
bus : EventBus,
query? : EventQuery = EventQuery::all(),
) -> (EventBus, Array[DispatchReport]) {
let events : Array[Event] = []
for record in self.query(query) {
events.push(record.event)
}
bus.publish_many(events)
}
///|
pub fn EventStore::topic_count(
self : EventStore,
topic_pattern : String,
) -> Int {
self.query(EventQuery::all().with_topic(topic_pattern)).length()
}
///|
pub fn EventStore::correlation_count(
self : EventStore,
correlation_id : String,
) -> Int {
self.query(EventQuery::all().with_correlation(correlation_id)).length()
}