Skip to content

A gate's consequence runs once

  • Context: a gate’s resolution is written before its consequence runs, and no transaction spans the gates and the ledger, the outbox or the turns, so a daemon that stopped in between lost the consequence: an approved proposal read accepted with its operation never applied.
  • Decision: a resolved gate records when its consequence ran (gates.applied_at), whether it succeeded or failed, unless its context ended first. The gates’ tick, which runs at the daemon’s start and after it, runs the consequence of every resolved gate without the mark that no call runs now. Every consequence runs once for its gate: the outbox queues only a held draft, the ledger records the proposals a decision was applied to (item_proposals.decided_at) in the decision’s own commit, and the turns store an answer once per gate. A consequence port that answers Once for a gate, the daemon’s for a round the daily cap held and a verb a gate held, has the gate marked run before the consequence runs: at most once, since nothing a second run reads records the first. The gate stays begun (gates.begun_at) until its consequence ends, and the tick after a stop reports a begun gate it does not run as a health warning naming it, once.
  • Consequence: a new gate kind’s consequence must be idempotent for its gate; a consequence that failed is a person’s to retry, never the tick’s.
  • Enforced by: TestAConsequenceACrashInterruptedRunsAtTheNextTick, TestTheTickLeavesAConsequenceInFlight, TestAFailedConsequenceIsNotRetriedByTheTick, TestADraftApprovedBeforeACrashIsSentOnceAfterIt, TestAProposalDecidedBeforeACrashAppliesOnce, TestAQuestionAnsweredBeforeACrashReachesItsSessionOnce, TestADecisionAppliesOnce, TestAnAnswerToTheSameGateIsDeliveredOnce, TestAOnceConsequenceIsMarkedBeforeItRuns, TestAReplayedHeldRoundRunsOnce, TestAReplayedGatedDelegateRunsOnce, TestAReplayedGatedReplySentAtOncePostsOnce, TestAOnceConsequenceAStopCutIsReportedAfterTheRestart. See Gates.