dig_events_protocol/cursor.rs
1//! The delivery cursor and its event envelope (SPEC §4).
2//!
3//! Every delivered event is stamped with a monotonic, per-instance [`Cursor`]. A subscriber
4//! remembers the last cursor it saw; on a gap (reconnect or lag) it calls `catch_up(since)` ONCE to
5//! backfill the missed range, then resumes the live stream. [`EmittedEvent`] is the envelope that
6//! flows over the live stream AND is returned by catch-up backfill.
7
8use serde::{Deserialize, Serialize};
9
10use crate::event::WalletEvent;
11
12/// A monotonic, per-instance sequence number stamped on delivered events.
13///
14/// A subscriber remembers the last cursor it saw; on a gap (reconnect or lag) it calls
15/// `catch_up(since)` ONCE to backfill the missed range, then resumes the live stream.
16/// Serializes as a bare `u64` on the wire.
17#[derive(
18 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
19)]
20pub struct Cursor(pub u64);
21
22impl Cursor {
23 /// The next cursor in sequence.
24 pub fn next(self) -> Cursor {
25 Cursor(self.0 + 1)
26 }
27}
28
29/// A delivered event paired with its monotonic [`Cursor`].
30///
31/// The engine stamps a per-instance cursor on every event as it is emitted; subscribers remember
32/// the last cursor and pass it to `catch_up` after a gap. This envelope is what flows over the
33/// subscription stream (live) and what catch-up returns (backfill).
34#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
35pub struct EmittedEvent {
36 /// The monotonic delivery cursor.
37 pub cursor: Cursor,
38 /// The event payload.
39 pub event: WalletEvent,
40}