1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//! The stream mechanism handle (ADR-019 §1; ADR-015).
//!
//! Publish/read/trim ops live on the stream-scoped handle — placement
//! mirroring the honker-rs starting artifact; the transactional twins
//! ride the `TxHandle` (ADR-021 §1).
use serde_json::Value;
use crate::Result;
use crate::event_receiver::EventReceiver;
use crate::future::BoxedFuture;
use crate::stream::StreamEvent;
/// The stream-scoped handle: publish, cursor reads, offsets, trim, and
/// the durable subscription.
pub trait StreamHandle: Send + Sync {
/// The stream name the handle was constructed with.
fn name(&self) -> &str;
/// Append an event to the stream's durable log (auto-commit).
/// Returns the assigned offset — engine-assigned, monotone per
/// stream, immutable.
fn publish<'a>(&'a self, payload: Value) -> BoxedFuture<'a, Result<i64>>;
/// Append a keyed event — [`StreamHandle::publish`]'s keyed twin.
/// The key is carried metadata (stored, round-tripped, no
/// engine-enforced behavioral role); the ordering guarantee stays
/// global FIFO by offset per stream (ADR-015 §1). A present key
/// must be non-empty (`InvalidName`). Returns the assigned
/// offset.
fn publish_with_key<'a>(
&'a self,
key: Option<String>,
payload: Value,
) -> BoxedFuture<'a, Result<i64>>;
/// Cursor read: events with `offset > ` cursor, `offset ASC`
/// (global FIFO — ADR-015 §4), up to `limit`. `limit` is an
/// extent argument (ADR-023 §2): `limit <= 0` reads nothing —
/// the empty `Vec`. A read from a
/// trimmed-away region resumes at the trim horizon's first
/// remaining row.
fn read_since<'a>(
&'a self,
offset: i64,
limit: i64,
) -> BoxedFuture<'a, Result<Vec<StreamEvent>>>;
/// Cursor read from a consumer's stored checkpoint (absent
/// consumer = 0). `consumer` is a consumer-local identifier
/// (non-empty only — `InvalidName`). `limit` is an extent
/// argument (ADR-023 §2): `limit <= 0` reads nothing — the
/// empty `Vec`.
fn read_from_consumer<'a>(
&'a self,
consumer: &str,
limit: i64,
) -> BoxedFuture<'a, Result<Vec<StreamEvent>>>;
/// Save a consumer's checkpoint — always explicit (no
/// auto-checkpoint cadence). Monotone: a save below the stored
/// checkpoint is a silent no-op (ADR-019 §6); the `Err` arm
/// carries `Database` only (ADR-021 §5). `consumer` is a
/// consumer-local identifier (non-empty only — `InvalidName`).
fn save_offset<'a>(&'a self, consumer: &str, offset: i64) -> BoxedFuture<'a, Result<()>>;
/// Inspect a consumer's stored checkpoint; absent consumer = 0
/// (the pre-save state, ADR-019 §1). `consumer` is a consumer-local
/// identifier (non-empty only — `InvalidName`).
fn get_offset<'a>(&'a self, consumer: &str) -> BoxedFuture<'a, Result<i64>>;
/// Bounded growth, consumer-invoked: delete events with
/// `offset <= horizon` (exact boundary; ADR-015 §5). The horizon
/// is a boundary argument (ADR-023 §2) — total: a negative
/// horizon deletes nothing, idempotently. Surviving
/// events keep their offsets (gaps legal, never renumbered); trim
/// emits no dedicated wake and no notify (on SQLite the
/// `data_version` watcher may still fire on the trim commit — any
/// committed write bumps it; a spurious hint, contract-legal).
/// Returns the deleted-row count.
fn trim_to<'a>(&'a self, horizon: i64) -> BoxedFuture<'a, Result<i64>>;
/// Durable consumption: attach a consumer that reads to the
/// current tail, resumes after restart from the stored offset,
/// and saves checkpoints explicitly (no `save_every`, no
/// save-on-drop). `consumer` is a consumer-local identifier
/// (non-empty only).
fn subscribe<'a>(&'a self, consumer: &str) -> BoxedFuture<'a, Result<Box<dyn EventReceiver>>>;
}