| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Keiro.Workflow.Awakeable.Schema
Description
The keiro_awakeables table: durable storage for awakeables (external
promises a workflow suspends on).
Mirrors the Keiro.Timer / Keiro.Timer.Schema split: this module owns the
row type, the AwakeableStatus lifecycle, and the hasql statements;
Keiro.Workflow.Awakeable owns the effectful authoring/completion surface.
registerAwakeableTxinserts apendingrow idempotently (theON CONFLICT DO NOTHINGEP-38'sawaitSteparming contract requires).lookupAwakeablereads a row back.completeAwakeableTxtransitions apendingrow tocompleted(guarded so a double signal is a no-op), andcancelAwakeableTxtransitions it tocancelled.countPendingAwakeablescounts outstanding promises — the seam EP-44 reads for itskeiro.workflow.awakeables.pendinggauge.
Callers normally use the re-exports / surface from Keiro.Workflow.Awakeable
rather than this module directly; EP-44 imports countPendingAwakeables here
without pulling in the effect surface.
Synopsis
- data AwakeableStatus
- data AwakeableRow = AwakeableRow {
- awakeableId :: !UUID
- ownerWorkflowName :: !Text
- ownerWorkflowId :: !Text
- status :: !AwakeableStatus
- payload :: !(Maybe Value)
- createdAt :: !UTCTime
- updatedAt :: !UTCTime
- completedAt :: !(Maybe UTCTime)
- statusToText :: AwakeableStatus -> Text
- statusFromText :: Text -> AwakeableStatus
- registerAwakeableTx :: UUID -> Text -> Text -> Transaction ()
- completeAwakeableTx :: UUID -> Value -> UTCTime -> Transaction Bool
- cancelAwakeableTx :: UUID -> Transaction (Maybe (Text, Text))
- lookupAwakeableStatusTx :: UUID -> Transaction (Maybe AwakeableStatus)
- lookupAwakeable :: forall (es :: [Effect]). Store :> es => UUID -> Eff es (Maybe AwakeableRow)
- countPendingAwakeables :: forall (es :: [Effect]). Store :> es => Eff es Int
Rows and status
data AwakeableStatus Source #
An awakeable's lifecycle state.
Pending— allocated and waiting for an external signal; the workflow is suspended on it.Completed— signalled with a payload; terminal.Cancelled— abandoned before it was signalled; terminal; also the decode fallback for an unrecognized stored value (the same defensive choice Keiro.Timer.Schema makes).
Instances
data AwakeableRow Source #
An awakeable row as stored: the deterministic id, the owning workflow's
name and instance id, the live status, the signalled payload (JSON, set
only once Completed), and the timestamps.
Constructors
| AwakeableRow | |
Fields
| |
Instances
| Generic AwakeableRow Source # | |||||
Defined in Keiro.Workflow.Awakeable.Schema Associated Types
| |||||
| Show AwakeableRow Source # | |||||
Defined in Keiro.Workflow.Awakeable.Schema Methods showsPrec :: Int -> AwakeableRow -> ShowS # show :: AwakeableRow -> String # showList :: [AwakeableRow] -> ShowS # | |||||
| Eq AwakeableRow Source # | |||||
Defined in Keiro.Workflow.Awakeable.Schema | |||||
| type Rep AwakeableRow Source # | |||||
Defined in Keiro.Workflow.Awakeable.Schema type Rep AwakeableRow = D1 ('MetaData "AwakeableRow" "Keiro.Workflow.Awakeable.Schema" "keiro-0.12.0.0-inplace" 'False) (C1 ('MetaCons "AwakeableRow" 'PrefixI 'True) (((S1 ('MetaSel ('Just "awakeableId") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 UUID) :*: S1 ('MetaSel ('Just "ownerWorkflowName") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text)) :*: (S1 ('MetaSel ('Just "ownerWorkflowId") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text) :*: S1 ('MetaSel ('Just "status") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 AwakeableStatus))) :*: ((S1 ('MetaSel ('Just "payload") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (Maybe Value)) :*: S1 ('MetaSel ('Just "createdAt") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 UTCTime)) :*: (S1 ('MetaSel ('Just "updatedAt") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 UTCTime) :*: S1 ('MetaSel ('Just "completedAt") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (Maybe UTCTime)))))) | |||||
statusToText :: AwakeableStatus -> Text Source #
statusFromText :: Text -> AwakeableStatus Source #
Storage (run inside the caller's transaction)
registerAwakeableTx :: UUID -> Text -> Text -> Transaction () Source #
Insert a pending awakeable row inside the caller's transaction.
Idempotent by ON CONFLICT (awakeable_id) DO NOTHING — exactly what EP-38's
"arm must be idempotent" contract needs, since a resumed workflow re-runs the
arming action on every resume until the awakeable resolves.
completeAwakeableTx :: UUID -> Value -> UTCTime -> Transaction Bool Source #
Transition a pending awakeable to completed, storing payload and the
completion time, inside the caller's transaction. The status =
guard makes a double-signal a no-op; returns pendingTrue only when this call
performed the transition (so the caller knows whether it was the one that
resolved the promise).
cancelAwakeableTx :: UUID -> Transaction (Maybe (Text, Text)) Source #
Transition a pending awakeable to cancelled inside the caller's
transaction, returning the owning workflow's (name, id) when this call
performed the transition. Only pending rows match, so an already-completed
(or already-cancelled) awakeable is left untouched and the call returns
Nothing.
The owner coordinates are returned because cancellation writes no journal
entry — there is no result value to record — so it is the only wake-source
lifecycle transition that would otherwise leave the owning workflow's
keiro_workflows row untouched. The caller flips that row in the same
transaction (see Keiro.Workflow.Awakeable.cancelAwakeable) so discovery
still surfaces the workflow.
lookupAwakeableStatusTx :: UUID -> Transaction (Maybe AwakeableStatus) Source #
Read an awakeable's current status inside the caller's transaction. Used after a guarded completion loses a row race, so the caller can distinguish a winning cancel (no journal append) from a winning signal (idempotent repair).