Skip to main content

EventJournal

Struct EventJournal 

Source
pub struct EventJournal { /* private fields */ }
Expand description

Per-view append-only event log with bounded retention.

Implementations§

Source§

impl EventJournal

Source

pub fn new(config: JournalConfig) -> Self

Source

pub fn config(&self) -> &JournalConfig

Source

pub fn is_enabled(&self) -> bool

Source

pub async fn epoch(&self) -> JournalEpoch

Source

pub async fn append_with<E>( &self, view_id: &str, key: &str, build_frame: impl FnOnce(u64) -> Result<Arc<Bytes>, E>, ) -> Result<Option<(u64, Arc<Bytes>)>, E>

Append one published event, building its frame from the offset it is about to take.

Reserving and committing happen under one lock so the offset embedded in the published frame is always the offset the record takes. A live subscriber checkpoints that value, so a mismatch would hand it a cursor that means something else.

Source

pub fn seal(&self)

Record that events were lost before the tape resumed.

Called when the stream starts live over a hole: a restore that hydrates state without resuming, or an ingestion runtime that gave up on its checkpoint. The retained records stay valid, but everything between them and the first live append is missing, and dense offsets would otherwise present that hole as continuous. Stop issuing offsets, permanently.

The final snapshot is taken while the parser is still running — it has to be, or an update can be cut between its VM write and its batch — so publishing continues after the consistency cut releases, for as long as encoding and storing the snapshot takes. Offsets issued in that window are not in the file, and a restore that adopted the epoch would re-issue them for different records under cursors that still validate.

Sealing at the cut makes “a shutdown snapshot is offset-exact” true rather than assumed. Events after it still publish and still reach subscribers; they simply carry no cursor, so a consumer’s last position stays at the cut and the resume after restart replays them.

Source

pub async fn mark_gap(&self)

Source

pub async fn window(&self, view_id: &str) -> ReplayWindow

Offsets this view can currently serve.

Prunes first: the age bound has to hold for a view that has gone quiet, otherwise expired records stay advertised and replayable.

Source

pub async fn replay_after( &self, view_id: &str, cursor: Option<&Cursor>, ) -> Result<Vec<JournalRecord>, ReplayError>

Every retained record strictly after cursor, in offset order.

A consumer that has seen nothing passes None, which replays the whole retained window.

Source

pub async fn dump(&self) -> JournalSnapshot

Durable form of the retained tape, for the snapshot payload.

Payload Arcs are cloned, not the bytes, so this stays cheap inside the snapshot’s consistency guard.

Source

pub async fn hydrate(&self, snapshot: JournalSnapshot, exact: bool)

Restore a dumped tape, so the advertised replay window survives a restart and a consumer’s cursor stays meaningful.

exact says whether the snapshot’s offsets are exactly what was published — true only for a snapshot taken at shutdown, under the consistency cut with nothing in flight. A periodic snapshot can be up to its write interval behind, so restoring one rewinds next_offset below offsets that have already been on the wire. Keeping the epoch there would re-issue those offsets for different records under a cursor that still validates: refused at first because the window has not caught up, then silently served once it has. A fresh epoch makes those cursors fail closed instead, which is the honest answer — after a rewind they genuinely cannot be honoured.

A snapshot without an epoch predates cursor epochs and is discarded — adopting it under a fresh epoch would be indistinguishable from a cold start anyway, and adopting its offsets under this tape’s epoch would validate cursors that should fail.

Retention is re-applied on load: a snapshot restored after a long outage must not advertise records the age bound has already retired.

Source

pub async fn entry_counts(&self) -> Vec<(String, u64)>

Retained record count per view, for snapshot diagnostics.

Source

pub async fn retained_bytes(&self) -> Vec<(String, u64)>

Retained bytes per view, for capacity reporting.

Source§

impl EventJournal

Source

pub async fn scope<F>(self: &Arc<Self>, future: F) -> F::Output
where F: Future,

Run the generated ingestion runtime with this server’s tape in scope, so it can report a stream discontinuity without being handed a journal it has no other use for.

Separate from the snapshot scope: the tape can be enabled with snapshots off, and that combination is exactly the one where a lost checkpoint has no other way to become visible.

Trait Implementations§

Source§

impl Debug for EventJournal

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more