| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Keiro.Snapshot.Schema
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
- data SnapshotRow = SnapshotRow {
- streamId :: !StreamId
- streamVersion :: !StreamVersion
- state :: !Value
- stateCodecVersion :: !Int
- regfileShapeHash :: !Text
- stateShapeHash :: !Text
- createdAt :: !UTCTime
- updatedAt :: !UTCTime
- data SnapshotWrite = SnapshotWrite {
- streamId :: !StreamId
- streamVersion :: !StreamVersion
- state :: !Value
- stateCodecVersion :: !Int
- regfileShapeHash :: !Text
- stateShapeHash :: !Text
- lookupSnapshot :: forall (es :: [Effect]). Store :> es => StreamId -> Int -> Text -> Text -> Eff es (Maybe SnapshotRow)
- lookupSnapshotRow :: forall (es :: [Effect]). Store :> es => StreamId -> Eff es (Maybe SnapshotRow)
- deleteSnapshotRow :: forall (es :: [Effect]). Store :> es => StreamId -> Eff es Bool
- writeSnapshotRow :: forall (es :: [Effect]). Store :> es => SnapshotWrite -> Eff es ()
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.
Constructors
| SnapshotRow | |
Fields
| |
Instances
data SnapshotWrite Source #
The fields needed to write a snapshot — SnapshotRow minus the
database-managed timestamps.
Constructors
| SnapshotWrite | |
Fields
| |
Instances
| Generic SnapshotWrite Source # | |||||
Defined in Keiro.Snapshot.Schema Associated Types
| |||||
| Show SnapshotWrite Source # | |||||
Defined in Keiro.Snapshot.Schema Methods showsPrec :: Int -> SnapshotWrite -> ShowS # show :: SnapshotWrite -> String # showList :: [SnapshotWrite] -> ShowS # | |||||
| Eq SnapshotWrite Source # | |||||
Defined in Keiro.Snapshot.Schema Methods (==) :: SnapshotWrite -> SnapshotWrite -> Bool # (/=) :: SnapshotWrite -> SnapshotWrite -> Bool # | |||||
| type Rep SnapshotWrite Source # | |||||
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.