pub struct CardsProjection { /* private fields */ }Expand description
The read model over a card’s seven kinds and an alias’s two.
Stateless apart from the name it answers to: everything it knows is in the tables, which is what makes a rebuild a replay rather than a reconstruction of anything held here.
Implementations§
Source§impl CardsProjection
impl CardsProjection
Sourcepub const NAME: &'static str = "cards_v4"
pub const NAME: &'static str = "cards_v4"
The consumer name, and so the identity of the cursor. See the module doc for what
the _v4 is for.
Sourcepub const KINDS: [&'static str; 10]
pub const KINDS: [&'static str; 10]
The kinds these streams carry. Naming them is not only a filter: it is what lets
the runner read through the (kind, position) index instead of walking the whole
log, and it is the reason apply may treat an unknown kind as a bug.
Sourcepub fn new() -> CardsProjection
pub fn new() -> CardsProjection
The projection this build folds under.
Trait Implementations§
Source§impl Default for CardsProjection
impl Default for CardsProjection
Source§impl Projection for CardsProjection
impl Projection for CardsProjection
Source§fn init(&mut self, tx: &Transaction<'_>) -> Result<()>
fn init(&mut self, tx: &Transaction<'_>) -> Result<()>
Create the tables — after dropping them, when the ones there predate this shape.
CREATE TABLE IF NOT EXISTS leaves an existing table as it is, so a cb_cards
written by an older build has no params_json, and the CREATE INDEX on model
that follows would fail on every open — which is what cardbox version did on a
store a cards_v3 build had created. The tables are a fold of the log and nothing
else, so an outdated one is dropped and folded again; crate::Store::open runs
the rebuild, having asked shape_outdated the same question before this ran.
Source§fn tolerates_truncation(&self) -> bool
fn tolerates_truncation(&self) -> bool
One event, folded.
The card’s id comes from the stream name rather than from meta: the stream is
what the store’s own decisions fold over, so it is the identity the invariants are
already stated in terms of, and a meta that disagreed with it would describe a
card that no append_if was ever protecting. An event of one of these kinds on a
stream that is not a card’s is a bug in whatever wrote it, and is reported rather
than skipped.
An unknown kind is likewise an error. kinds() is what the runner filters on, so
one arriving here means the filter and this match have drifted apart, and a fold
that quietly ignored it would leave a read model missing rows with nothing saying so.
Yes — and only because every removal announces itself first.
The default is false, and for an accumulating model the default is the right
answer: sample_rows, eval_count and cb_blobs.refs are running totals, and a
replay over a log missing part of its input produces a smaller number with nothing
about it saying so. What makes this model different is the shape of the only
removal it allows.
A prune is retain(Plan::Streams, ..) over whole card-<id> streams, and a
cards_pruned event on PRUNE_STREAM is appended before it — that stream is
never itself retained, so the journal survives what it describes. On a rebuild the
pruned cards’ events are gone, so no row is ever created for them and no counter
ever incremented; the journal event then replays over an absent card and
[purge] returns without touching anything. The totals come out the same as they
were, because the events that would have moved them and the event that moved them
back are both absent.
That is the whole of the claim, and it is narrow on purpose: it holds for a
removal of whole card streams that a journal event announced, and it would not
hold for a bare eventsdb::sqlite::Plan::Before or OlderThan over this log.
Neither is reachable — crate::Store exposes retain_streams and nothing else.
Source§fn name(&self) -> &str
fn name(&self) -> &str
Source§fn kinds(&self) -> Option<Vec<String>>
fn kinds(&self) -> Option<Vec<String>>
None sees every kind. Read moreAuto Trait Implementations§
impl Freeze for CardsProjection
impl RefUnwindSafe for CardsProjection
impl Send for CardsProjection
impl Sync for CardsProjection
impl Unpin for CardsProjection
impl UnsafeUnpin for CardsProjection
impl UnwindSafe for CardsProjection
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more