///|
pub(all) struct EventCursor {
start_sequence : Int
limit : Int
pattern : String
} derive(Eq, @debug.Debug)
///|
pub(all) struct TapeWindow {
cursor : EventCursor
entries : Array[TapeEntry]
next_cursor : EventCursor
complete : Bool
} derive(Eq, @debug.Debug)
///|
pub fn event_cursor(
start_sequence? : Int = 0,
limit? : Int = 100,
pattern? : StringView = "**",
) -> EventCursor {
{
start_sequence: if start_sequence < 0 {
0
} else {
start_sequence
},
limit: if limit <= 0 {
1
} else {
limit
},
pattern: pattern.to_owned(),
}
}
///|
pub fn EventCursor::next_from(
self : EventCursor,
sequence : Int,
) -> EventCursor {
{ ..self, start_sequence: if sequence < 0 { 0 } else { sequence } }
}
///|
pub fn EventCursor::with_limit(self : EventCursor, limit : Int) -> EventCursor {
{ ..self, limit: if limit <= 0 { 1 } else { limit } }
}
///|
pub fn EventCursor::with_pattern(
self : EventCursor,
pattern : StringView,
) -> EventCursor {
{ ..self, pattern: pattern.to_owned() }
}
///|
pub fn EventCursor::to_wire(self : EventCursor) -> String {
"start=\{self.start_sequence};limit=\{self.limit};pattern=\{escape_wire_text(self.pattern)}"
}
///|
pub fn EventTape::window(
self : EventTape,
cursor : EventCursor,
) -> Result[TapeWindow, EventRailError] {
match topic_pattern(cursor.pattern) {
Err(err) => Err(err)
Ok(parsed) => {
let entries : Array[TapeEntry] = []
let mut next_sequence = cursor.start_sequence
let mut complete = true
for entry in self.entries {
if entry.sequence < cursor.start_sequence {
continue
}
match parsed.matches_topic(entry.event.topic) {
Err(err) => return Err(err)
Ok(false) => ()
Ok(true) =>
if entries.length() < cursor.limit {
entries.push(entry)
next_sequence = entry.sequence + 1
} else {
complete = false
break
}
}
}
Ok({
cursor,
entries,
next_cursor: cursor.next_from(next_sequence),
complete,
})
}
}
}
///|
pub fn TapeWindow::len(self : TapeWindow) -> Int {
self.entries.length()
}
///|
pub fn TapeWindow::is_empty(self : TapeWindow) -> Bool {
self.entries.length() == 0
}
///|
pub fn TapeWindow::events(self : TapeWindow) -> Array[Envelope] {
self.entries.map(entry => entry.event)
}
///|
pub fn TapeWindow::to_tape(self : TapeWindow) -> EventTape {
let mut tape = event_tape()
for entry in self.entries {
tape = tape.append(entry.event)
}
tape
}
///|
pub fn TapeWindow::manifest_lines(self : TapeWindow) -> Array[String] {
let lines : Array[String] = []
lines.push("cursor=\{self.cursor.to_wire()};complete=\{self.complete}")
for entry in self.entries {
lines.push(entry.to_manifest_line())
}
lines.push("next=\{self.next_cursor.to_wire()}")
lines
}
///|
pub fn TapeWindow::manifest(self : TapeWindow) -> String {
self.manifest_lines().join("\n")
}
///|
pub fn TapeWindow::summary(self : TapeWindow) -> String {
"window start=\{self.cursor.start_sequence} limit=\{self.cursor.limit} entries=\{self.entries.length()} complete=\{self.complete} next=\{self.next_cursor.start_sequence}"
}
///|
pub fn EventTape::page_count(self : EventTape, limit : Int) -> Int {
let normalized = if limit <= 0 { 1 } else { limit }
if self.entries.length() == 0 {
0
} else {
(self.entries.length() + normalized - 1) / normalized
}
}