Skip to main content

Module transaction

Module transaction 

Source
Expand description

The one durable transition protocol: prepare → CAS append → commit (spec §8.2, §8.3, §15.2).

This module is the state machine that sits between a WireEnvelope and a KernelRecord. It owns exactly the decisions that must not be re-implemented per host: whether an input is a replay, whether it may be accepted at all, which record it becomes, and when the effects that record’s step planned become visible.

Four properties shape the API, and each is meant to be unrepresentable-if-violated rather than merely documented:

  1. Abort’s boundary is strictly before the append (§8.3). There is no state in which a record is durable and still sits in the candidate slot, because KernelTransaction::commit is the call a host makes after its CAS append succeeded, and it consumes the candidate. A host that gets an error out of commit, or crashes inside it, therefore has no abort to reach for — the transaction poisons itself and the only way forward is KernelTransaction::rebuild_from_records. “Append succeeded, commit failed, so we rolled back” is not a control flow this type can express.
  2. Every rejection is byte-for-byte zero mutation (§15.2). prepare mutates nothing until the very last statement, which is the one that fills the candidate slot; the tests assert this by cloning the whole transaction and comparing it after a rejected prepare.
  3. Idempotency is anchored on input_id + the durable journal (DEC-2), never on a bounded in-memory window. The lookup goes through RecordIndex, whose production implementation reads the journal; the historical 256-entry FIFO turned “the same delivery arrived twice” into a fail-closed rejection as soon as the run got long enough.
  4. An already-resolved effect resolves to Replayed, never to a second record (DEC-1). Reporting that case as Prepared while returning the old step_seq is the live dead end this protocol exists to remove.

What this layer deliberately does not do: it never plans a step itself (the caller passes a planner, and Phase 3/4 supplies the real one), and it never rebuilds itself after a conflict — rebuild/retry is the host-side loop of Task 7b, and this module only offers it a verified entry point.

Structs§

CheckpointAdvice
The soft-watermark crossing of §12.3, with the numbers that justify it.
CheckpointBoundary
The prefix a checkpoint would cover (§12.3).
CommittedTransition
One durable transition, after the host’s append and this runtime’s commit.
DurableHead
The journal head this runtime believes in: the CAS precondition of the next append.
InMemoryRecordIndex
In-memory RecordIndex, for tests and for hosts whose journal is itself in memory (§8.4).
KernelTransaction
The prepare/commit/abort state machine of §8.2.
PlanContext
What the planner is given. Everything it needs to decide, and nothing that would let it depend on the host’s wall clock or on a default that may drift between binaries: config is the configuration this operation froze in its genesis record.
TailUsage
How much tail the operation is carrying since its last acked checkpoint.

Enums§

TailPressure
Where the tail sits against its bounds. Full is not a latch — an acked checkpoint moves it straight back to Nominal.

Traits§

RecordIndex
Lookup from an input_id to the record it already produced.
TransitionStep
The one thing the transaction layer needs to know about a planned step.