teksilo_telemetry/queue.rs
1// SPDX-License-Identifier: MPL-2.0
2// SPDX-FileCopyrightText: 2026 FernTech
3
4//! Event queue — `EventQueue` trait + two impls.
5//!
6//! Adapters that buffer events for later transmission depend on the
7//! [`EventQueue`] trait so the choice of in-memory vs. persistent
8//! backing is a deployment detail. Both impls have the same FIFO
9//! semantics (oldest event drained first); only [`PersistentEventQueue`]
10//! survives process restart.
11//!
12//! - [`InMemoryEventQueue`] — `Mutex<VecDeque<OwnedEvent>>`. Default
13//! for tests and for adapters that consider events ephemeral.
14//! - [`PersistentEventQueue`] — backed by [redb] at a path under
15//! [`AppPaths::data_dir()`](teksilo_settings::AppPaths::data_dir).
16//! Pure-Rust, no C deps, ~250–400 KB binary footprint vs. SQLite's
17//! ~1 MB. Atomic writes, MVCC reads, single-writer.
18//!
19//! [redb]: https://crates.io/crates/redb
20
21mod mem;
22mod persistent;
23
24pub use mem::InMemoryEventQueue;
25pub use persistent::{PersistentEventQueue, PersistentQueueError};
26
27use teksilo_core::telemetry::OwnedEvent;
28
29/// FIFO event buffer with capped size and oldest-eviction.
30///
31/// `Send + Sync` is required because adapters typically own a worker
32/// thread that drains the queue while the UI thread pushes; the
33/// trait's contract is "thread-safe enough for a producer/consumer
34/// pair."
35pub trait EventQueue: Send + Sync + 'static {
36 /// Append an event to the tail. If the queue is at capacity,
37 /// the oldest entry is dropped (FIFO eviction).
38 fn push(&self, event: OwnedEvent);
39
40 /// Take up to `n` events from the head, removing them. Used by
41 /// adapter workers to assemble batches for HTTP transmission.
42 fn drain_batch(&self, n: usize) -> Vec<OwnedEvent>;
43
44 /// Number of events currently buffered. Includes events queued
45 /// for retry.
46 fn len(&self) -> usize;
47
48 fn is_empty(&self) -> bool {
49 self.len() == 0
50 }
51
52 /// Drop everything without sending. Called on consent revocation
53 /// and on `UsageReporter::erase_remote_data`. Implementations
54 /// MUST guarantee no buffered event escapes after this returns.
55 fn discard_all(&self);
56
57 /// Snapshot the head of the queue (clone). Used by the
58 /// `PrivacySettings` "Inspect data sent" view. Best-effort — the
59 /// returned events may have been drained by the time the caller
60 /// reads them.
61 fn peek_recent(&self, n: usize) -> Vec<OwnedEvent>;
62}