Documentation
¶
Overview ¶
Package reserved implements the reserved-commit facility (@D05b): the engine-level lifecycle that cal proposals, bal holds, blob leases, and entity staged writes are all instances of. Participants supply only a conflict predicate and a weight policy; the facility owns the tentative-row convention, the state walk, and the sweep.
The convention ¶
A guard-bearing table adopts three columns (see sql.go for the DDL fragment):
txn_id TEXT NULL -- owning transaction; set at reserve state TEXT NOT NULL DEFAULT 'committed' reserve_deadline INTEGER NULL -- unix nanoseconds; set while reserved
Only two states are ever persisted: 'committed' (the default — every ordinary row) and 'reserved' (a tentative row inside its TTL window). The four terminal outcomes of §D05b's walk
reserved → confirmed | released | expired | invalidated
are transitions, not resting states: Confirm CAS-flips the row to 'committed'; Release deletes it; the sweeper deletes it after its deadline (expired); and under optimistic weight a competing transaction's confirmation is what makes the loser's own confirmation fail (invalidated) — the loser learns its fate at its next CAS, and its rows are released by its coordinator or collected at TTL. bal's journal state column (@B10) is this convention's first schema instance, promoted here to substrate-wide practice.
The two weights ¶
Each participant declares how its reserved rows count in admission:
- Pessimistic (2PS semantics): reserved rows are honoured like real commits by every guard — a reserved debit reduces available balance, a reserved slot refuses competitors — until confirmation or expiry.
- Optimistic (3PS semantics): reserved rows are invisible to admission; conflicting reservations coexist, and the first confirmer wins.
Deadline authority ¶
The deadline is authoritative; the sweeper is only hygiene. Guard predicates compare reserve_deadline inline (see GuardPredicate), so a lapsed reservation stops counting the instant it expires and cannot be confirmed even while unswept. This is what makes coordinator death survivable: an abandoned reservation self-releases by clock, not by cleanup.
Doctrine: guards never use accelerators ¶
Enforcement reads go to the guard plane — the SQL tables carrying this convention — always. In-memory accelerators are commit-fed and serve application traversal only; a commit-fed accelerator answering a tentative-aware question would answer wrongly (@D05c tier 1, and the G-12 lesson written down as law).
Visibility taxonomy (@D05c) ¶
tier 1 guard plane tentative-aware, mandatory (per weight) tier 2 advisory planes weight-optional, sweep-cleaned tier 3 analytic planes commit-fed, strictly
See VisibilityTier and PredicateFor.
Index ¶
- func ApplicationPredicate() string
- func ConventionColumns() string
- func ConventionIndexes(prefix, table string) string
- func Deadline(now ot.Instant, ttl time.Duration) int64
- func GuardPredicate(w Weight) (fragment string, binds int)
- func PredicateFor(tier VisibilityTier, w Weight) (fragment string, binds int)
- func Release(ctx context.Context, q Querier, table, txnID string) (int64, error)
- type Outcome
- type Querier
- type State
- type Sweeper
- type VisibilityTier
- type Weight
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ApplicationPredicate ¶
func ApplicationPredicate() string
ApplicationPredicate returns the SQL fragment for application (non- guard) reads: committed rows only, unconditionally. Application reads never see reservations regardless of weight (@D05b visibility rule).
func ConventionColumns ¶
func ConventionColumns() string
ConventionColumns returns the three column definitions of the tentative-row convention, for embedding in a participant table's CREATE TABLE. The state default is 'committed' so that every row written outside the reserve path is real by construction — adopting the convention changes nothing for existing writers.
func ConventionIndexes ¶
ConventionIndexes returns CREATE INDEX statements for a participant table: a partial index over reserved rows by txn_id (the CAS transitions' access path) and one by deadline (the sweeper's). prefix follows the house table-prefix pattern; table is the full table name.
func Deadline ¶
Deadline computes a reservation deadline as now + ttl, in the canonical persisted representation (unix nanoseconds, UTC). A non-positive ttl yields a deadline already in the past, which the guard plane treats as lapsed immediately — reserving with one is a caller error that the clock, not a validation branch, punishes.
func GuardPredicate ¶
GuardPredicate returns the SQL fragment a guard-plane read appends to its WHERE clause, per the participant's declared weight. The caller binds nowNano (unix nanoseconds) once for the pessimistic form; the optimistic form takes no bind.
Pessimistic: committed rows plus reserved rows still inside their window — a live reservation is honoured like a commit. The deadline comparison is inline because the deadline is authoritative: a lapsed reservation stops counting here, immediately, sweeper or no sweeper.
Optimistic: committed rows only — reservations are invisible to admission, and conflicts resolve at confirmation (first confirmer wins).
func PredicateFor ¶
func PredicateFor(tier VisibilityTier, w Weight) (fragment string, binds int)
PredicateFor returns the read predicate for a visibility tier (@D05c). TierGuard defers to the weight; TierAdvisory with a pessimistic weight may ingest live reservations (and thereby joins the sweeper's cleanup obligations); TierAnalytic is commit-fed, strictly.
Types ¶
type Outcome ¶
type Outcome int
Outcome classifies the result of a Confirm attempt. Exactly one outcome is returned per attempt; OutcomeConfirmed is the only success.
const ( // OutcomeConfirmed: the CAS fired — the reservation's rows are now // committed. OutcomeConfirmed Outcome = iota // OutcomeAlreadyConfirmed: the rows are already committed under // this txn_id — an idempotent retry of a confirmation that won. OutcomeAlreadyConfirmed // OutcomeExpired: the reservation's deadline lapsed before the CAS. // The deadline is authoritative: this outcome is returned even if // the sweeper has not yet collected the rows. OutcomeExpired // OutcomeGone: no rows carry this txn_id — the reservation was // released, invalidated and swept, or never existed here. OutcomeGone )
func Confirm ¶
func Confirm(ctx context.Context, q Querier, table, txnID string, now ot.Instant) (Outcome, int64, error)
Confirm CAS-flips every live reserved row owned by txnID in table to committed:
UPDATE <table> SET state='committed', reserve_deadline=NULL WHERE txn_id=? AND state='reserved' AND reserve_deadline > <now>
txn_id is retained on the committed rows, which is what makes retries classifiable (OutcomeAlreadyConfirmed) and gives the audit trail its thread. Rows-affected is checked; when the CAS does not fire, the outcome is classified — never guessed:
- rows exist, reserved, deadline lapsed → OutcomeExpired
- rows exist, committed under this txn → OutcomeAlreadyConfirmed
- no rows carry this txn_id → OutcomeGone
The deadline comparison makes expiry authoritative at the moment of confirmation: a reservation past its window cannot be confirmed even if the sweeper has not run.
type Querier ¶
type Querier interface {
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
}
Querier is the subset of database/sql shared by *sql.DB and *sql.Tx. Every transition in this file takes a Querier so that participants can run it inside their own transactions — the guard-locality law (@C04a): a guarded transition's read and write commit together.
type State ¶
type State string
State is the persisted lifecycle state of a row under the convention. Only StateCommitted and StateReserved are ever stored; the terminal outcomes of the reserved walk are transitions (see Outcome).
const ( // StateCommitted marks an ordinary, fully real row — the column // default, and the only state application reads ever see. StateCommitted State = "committed" // StateReserved marks a tentative row inside its TTL window, owned // by the transaction named in txn_id. StateReserved State = "reserved" )
func ReserveValues ¶
ReserveValues returns the column values a participant's reserve-path INSERT binds for the convention columns: (txn_id, state, reserve_deadline). The INSERT itself belongs to the participant — the facility does not know its table shape — but the tentative marking is uniform.
type Sweeper ¶
type Sweeper struct {
// contains filtered or unexported fields
}
Sweeper collects lapsed reservations from every registered adopter of the tentative-row convention. It implements gc.Sweeper and plugs into the existing GC worker abstraction.
The sweeper is hygiene, not enforcement: the deadline is authoritative (guard predicates and Confirm compare reserve_deadline inline), so a lapsed reservation has already stopped counting everywhere before the sweeper ever sees it. What the sweep reclaims is storage and index space — finiteness (@D04b), not correctness.
func NewSweeper ¶
func NewSweeper() *Sweeper
NewSweeper creates an empty Sweeper. Adopting tables register with Register; a sweeper with no registrations sweeps nothing and reports zeroes, which is valid (gc.Report documents zero values as such).
func (*Sweeper) Register ¶
Register adds a convention-adopting table to the sweep set. Safe for concurrent use with Sweep.
func (*Sweeper) Sweep ¶
Sweep deletes reserved rows whose deadline has lapsed, across every registered table. Per-table failures are counted in Report.Errors and do not abort the cycle — one adopter's trouble must not starve the others' hygiene. Examined counts reserved rows seen; Collected counts rows deleted. Duration is stamped by the gc.Worker.
type VisibilityTier ¶
type VisibilityTier int
VisibilityTier names the three planes of the @D05c taxonomy. It exists so that read paths can declare which tier they serve and take their predicate from PredicateFor rather than hand-rolling one.
const ( // TierGuard is the guard plane: tentative-aware, mandatory. Sees // committed rows plus live reserved rows per the declared weight. TierGuard VisibilityTier = iota // TierAdvisory covers derived availability-type structures (cal's // occupancy index). May ingest reservations when the participant's // weight is pessimistic; correctness never depends on this tier. TierAdvisory // TierAnalytic covers rollups, FTS, events, caches, and the // in-memory graph: commit-fed, strictly. A reserved row is // invisible here; it becomes visible at confirm. TierAnalytic )