pub struct EventQueue { /* private fields */ }Implementations§
Source§impl EventQueue
impl EventQueue
pub fn new(store: Arc<CacheStore>, events: Arc<EventsClient>) -> Self
pub fn with_logger(self, logger: Arc<Logger>) -> Self
Sourcepub fn enqueue(self: &Arc<Self>, envelope_json: &str) -> RovenueResult<()>
pub fn enqueue(self: &Arc<Self>, envelope_json: &str) -> RovenueResult<()>
Validate envelope_json (must parse as an EventEnvelope whose
eventType starts with one of QUEUED_EVENT_PREFIXES — anything
else is rejected as InvalidArgument, this is not a
general-purpose enqueue), persist it
(bounded at 100 entries, drop-oldest — see
CacheStore::append_queued_event), then trigger a best-effort
background drain. The caller (funnel sessions emit pre-stamped
envelopes) is responsible for stamping
version/eventId/subscriberId before calling this — those
fields must already be baked into envelope_json so a drain that
runs after a log_out() still posts under the identity the event
was actually attributed to.
Sourcepub fn trigger_drain(self: &Arc<Self>)
pub fn trigger_drain(self: &Arc<Self>)
Spawns a background thread to run drain_once.
Fire-and-forget and non-blocking — callers on the configure()/
set_foreground() paths must never wait on network I/O here.
Sourcepub fn drain_once(&self)
pub fn drain_once(&self)
Peek (oldest first) -> POST /v1/events -> delete on 2xx. On
connectivity failure / 5xx/429, or a non-poison 4xx (401/403 auth
blip, 408, etc. — see RovenueError::is_poison), the entry (and
everything behind it) is retained and the drain stops —
at-least-once delivery, safe because the server dedupes on the
deterministic event id and bounded because the queue itself is
capped at 100 with drop-oldest. Only a genuine envelope rejection
(400/422) is poison: retaining it would wedge every later entry
behind it forever, so it is dropped (loudly logged) and the drain
continues with the next entry.
Single-in-flight: a drain already running makes this call a no-op —
the in-progress drain will pick up anything enqueued meanwhile since
it re-peeks the store on every iteration. There is a narrow window
between the drain loop seeing an empty queue and the flag actually
clearing where a concurrent enqueue() can land its own no-op
drain; see the re-arm check below.