keiro
Safe HaskellNone
LanguageGHC2024

Keiro.Snapshot.Schema

Contents

Description

The keiro_snapshots table: persistence for aggregate snapshots.

One row per stream holds the latest snapshot of its folded state as JSONB, tagged with the stateCodecVersion, regfileShapeHash, and stateShapeHash that produced it. lookupSnapshot fetches the newest row matching all three discriminators (so incompatible snapshots are simply not found). Within one discriminator tuple, writeSnapshotRow keeps only the highest stream version, so a late or out-of-order write cannot regress the snapshot.

A write with a different discriminator deliberately replaces the row even at a lower stream version. This lets a rolled-back deployment reclaim the single snapshot slot instead of being locked out by a newer codec forever. During a mixed-version deployment, however, writers with incompatible codecs can thrash that row and each side will miss the other's snapshot. The cost is repeated full replay, never incorrect state: the event log remains the source of truth.

This module is the storage layer beneath Keiro.Snapshot; callers normally go through hydrateWithSnapshot and writeSnapshot rather than these statements directly.

Synopsis

Rows

data SnapshotRow Source #

A snapshot row as read back from keiro_snapshots: the stored state JSON, the streamVersion it captures, the stateCodecVersion and regfileShapeHash and stateShapeHash that gate compatibility, and the create/update timestamps.

Instances

Instances details
Generic SnapshotRow Source # 
Instance details

Defined in Keiro.Snapshot.Schema

Associated Types

type Rep SnapshotRow 
Instance details

Defined in Keiro.Snapshot.Schema

Show SnapshotRow Source # 
Instance details

Defined in Keiro.Snapshot.Schema

Eq SnapshotRow Source # 
Instance details

Defined in Keiro.Snapshot.Schema

type Rep SnapshotRow Source # 
Instance details

Defined in Keiro.Snapshot.Schema

data SnapshotWrite Source #

The fields needed to write a snapshot — SnapshotRow minus the database-managed timestamps.

Instances

Instances details
Generic SnapshotWrite Source # 
Instance details

Defined in Keiro.Snapshot.Schema

Associated Types

type Rep SnapshotWrite 
Instance details

Defined in Keiro.Snapshot.Schema

type Rep SnapshotWrite = D1 ('MetaData "SnapshotWrite" "Keiro.Snapshot.Schema" "keiro-0.12.0.0-inplace" 'False) (C1 ('MetaCons "SnapshotWrite" 'PrefixI 'True) ((S1 ('MetaSel ('Just "streamId") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 StreamId) :*: (S1 ('MetaSel ('Just "streamVersion") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 StreamVersion) :*: S1 ('MetaSel ('Just "state") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Value))) :*: (S1 ('MetaSel ('Just "stateCodecVersion") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int) :*: (S1 ('MetaSel ('Just "regfileShapeHash") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text) :*: S1 ('MetaSel ('Just "stateShapeHash") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text)))))
Show SnapshotWrite Source # 
Instance details

Defined in Keiro.Snapshot.Schema

Eq SnapshotWrite Source # 
Instance details

Defined in Keiro.Snapshot.Schema

type Rep SnapshotWrite Source # 
Instance details

Defined in Keiro.Snapshot.Schema

type Rep SnapshotWrite = D1 ('MetaData "SnapshotWrite" "Keiro.Snapshot.Schema" "keiro-0.12.0.0-inplace" 'False) (C1 ('MetaCons "SnapshotWrite" 'PrefixI 'True) ((S1 ('MetaSel ('Just "streamId") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 StreamId) :*: (S1 ('MetaSel ('Just "streamVersion") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 StreamVersion) :*: S1 ('MetaSel ('Just "state") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Value))) :*: (S1 ('MetaSel ('Just "stateCodecVersion") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int) :*: (S1 ('MetaSel ('Just "regfileShapeHash") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text) :*: S1 ('MetaSel ('Just "stateShapeHash") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text)))))

Storage

lookupSnapshot :: forall (es :: [Effect]). Store :> es => StreamId -> Int -> Text -> Text -> Eff es (Maybe SnapshotRow) Source #

Fetch the latest snapshot for a stream that matches all three codec discriminators. Returns Nothing when no compatible snapshot exists, so an incompatible one is treated as absent.

lookupSnapshotRow :: forall (es :: [Effect]). Store :> es => StreamId -> Eff es (Maybe SnapshotRow) Source #

Fetch the advisory snapshot row for a stream without applying codec compatibility filtering. This is the operator-inspection surface; runtime hydration must continue to use lookupSnapshot.

deleteSnapshotRow :: forall (es :: [Effect]). Store :> es => StreamId -> Eff es Bool Source #

Delete a stream's advisory snapshot. Returns True when a row existed. Event history is untouched, so the next hydration falls back to full replay.

writeSnapshotRow :: forall (es :: [Effect]). Store :> es => SnapshotWrite -> Eff es () Source #

Upsert a snapshot row for its stream. For the same discriminator tuple, the write only takes effect when its streamVersion is at least the stored one. Any incompatible discriminator replaces the row even at a lower version so codec rollback can make progress; see the module header for the mixed-deployment performance caveat.