Documentation
¶
Overview ¶
Package continuation is RFC-199 Tier 2's continuation-under-fault replay driver.
A cursor scan that exceeds a row/byte/time limit does not return everything — it mints a CONTINUATION token and the caller resumes the scan, in a fresh transaction at a new read version, from that token. Every byte of that token is a place a bug can hide: an off-by-one at a page boundary, a plan hash baked into (or missing from) the token, a resume that re-scans or skips a row, a version-path-dependence when the data changed underneath the token. The record layer has hand-written point tests for a handful of these (delete-before-continuation, insert-around-continuation, index-delete-past-continuation); this driver is the seeded sweep that turns those point samples into a loop-until-bug fuzzer over the deterministic SimFDB backend.
The oracle is an INDEPENDENT Go model, not the engine judging itself. For a seeded record set the exact scan order is known a priori — records come back in primary-key (tuple) order, a VALUE index comes back in (indexed-value, primary-key) order — so the model is computed directly from the seeded (pk, price) pairs. Four checks, all airtight:
- PAGINATION EQUIVALENCE — paginate each scan (record / index, forward / reverse) at every page size, resuming from the continuation each page in a FRESH transaction, and assert the concatenation equals the model. Page size 1 is the hard case: every single row round-trips through a continuation token, so any token-encoding defect diverges immediately.
- PREFIX-DELETE INVARIANCE — mint a continuation mid-scan, then in a separate committed transaction (version bump) delete a record the scan ALREADY passed, resume, and assert the un-scanned tail is untouched: a change to the scanned prefix must not perturb the resume.
- TAIL-DELETE REFLECTED — mint a continuation mid-scan, delete a record the scan has NOT yet reached, resume, and assert the tail equals the model with exactly that row removed: a delete past the continuation point must be skipped, not double-counted or lost.
- TAIL-DELETE UNDER AN INJECTED FAULT — the same tail delete, but committed through a targeted fault (InjectOnce) in a raw single-commit transaction (db.Run would retry the fault away): the resume must reflect the fault's TRUE outcome — not_committed(1020) rolls the delete back (tail unchanged), and commit_unknown(1021) leaves it durable or not depending on which of its two real branches fired (tail minus the key, or tail unchanged).
The continuation itself is a fault (each page boundary is a "the transaction ended, resume from bytes" event) as is the between-page version bump; the fourth check adds a targeted commit fault on top. Fully deterministic over SimFDB: same seed ⇒ same pages, same verdict.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Result ¶
Result is the driver's rich outcome: the hunt.Report plus the number of pages scanned (work done).
type Workload ¶
type Workload struct {
Records int // records seeded per run (default 40)
PKDomain int64 // primary keys drawn from [0,PKDomain); > Records leaves gaps (default 200)
}
Workload is the continuation-replay driver, a hunt.Workload. It ignores the record-oriented hunt.Config. The scans run fault-free; the fourth oracle injects a targeted commit fault on the between-page write only (via a raw single-commit transaction), so the scan model stays exact.