Skip to content

Views v3 ledger: report contention as busy, not unreadable or schema drift - #1108

Open
aft-alfonso[bot] wants to merge 9 commits into
mainfrom
land/v3-ledger-busy
Open

aft-alfonso[bot] wants to merge 9 commits into
mainfrom
land/v3-ledger-busy

Conversation

@aft-alfonso

@aft-alfonso aft-alfonso Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Two Windows CI failures today (a branch-switch round trip in #1098's queue group and on main at 3d2e786) refused a call-graph view with reservation_ledger_unreadable. The old error dropped its cause, and the failure didn't reproduce natively, so this PR doesn't claim to fix those incidents. It fixes what the code shows, and it adds the path, the operation and the underlying error to every ledger refusal, so a recurrence names its site.

  • Busy WAL checkpoint: a wal_checkpoint(TRUNCATE) that reports busy now returns a typed SQLITE_BUSY with the checkpoint counters (reservation_ledger_busy: checkpoint WAL <path>: ... busy=1 ...) instead of reservation_ledger_unreadable.
  • Unstable measurement: a namespace that doesn't stabilize after 8 measurements or corrections reports busy.
  • Busy read as schema drift (found by a new test, on Linux and Windows): v3 initialization and format validation turned SQLITE_BUSY into schema_drift, which reads as a damaged store. Contention is kept now; real malformed schemas keep their drift checks.
  • Callgraph: busy carries through plane publication, base references, the registry and the driver to the call-graph view, which already reports busy as "building, retry". The classification across layers matches known message prefixes, which is weaker than a typed error.

Tests, each with real SQLite contention, a recovery check, and a check that it fails without the fix: checkpoint_contention_is_busy_and_preserves_sqlite_cause, busy_validation_is_not_persisted_as_schema_drift, changing_derived_database_reports_busy_then_measurement_recovers, v3_checkpoint_contention_reaches_checkout_reader_as_busy and v3_busy_ledger_during_view_construction_is_retryable. 181 v3, callgraph and migration tests pass, plus the Windows target check.


Summary by cubic

v3 reservation-ledger contention now reports as transient busy instead of reservation_ledger_unreadable or schema_drift, which previously read as a damaged store. Base-plane completion owned by another driver also classifies as busy. Each ledger refusal records the ledger path, the failing operation, and the SQLite cause, so a recurrence names its site. This doesn't claim to fix the two Windows CI incidents that motivated it; neither reproduced natively.

Busy classification

  • A busy wal_checkpoint(TRUNCATE) returns a typed SQLITE_BUSY with WAL counters; namespaces and registries that don't settle after 8 attempts report busy.
  • v3 validation and initialization keep SQLITE_BUSY instead of converting it to schema drift; genuine malformed or incomplete schemas still fail drift checks.
  • Permanent ledger failures still become migration storage_gap refusals; busy is never swallowed.

Contention propagation

  • Busy classification carries through plane publication, base references, the driver, and view construction; the call-graph view access keeps its SQLite busy form, which callers already treat as retryable, instead of an unreadable graph.
  • Base completion fenced by another driver answers busy until the base becomes ready.
  • Tests use real SQLite contention with recovery checks and fail without the fix.

Written for commit 7bf5d34. Summary will update on new commits.

View guided diff Turn on auto-fix

ualtinok and others added 6 commits October 28, 2026 21:37
Co-authored-by: alfonso-aft <289616620+alfonso-aft@users.noreply.github.com>
The historical Windows CI failure was not reproduced in native branch-switch runs. This fixes mislabeling found in code: a busy WAL checkpoint and an inventory that changes through eight confirmation attempts are transient contention, not an unreadable ledger.

Exercise a real pinned WAL reader through checkout callgraph acquisition and deterministic derived SQLite growth during measurement. Keep corrupt/incomplete peer-ledger admission refused; update those assertions only to require operation/path/source diagnostics rather than a cause-free code. Preserve migration storage gaps for permanent ledger failures without swallowing busy.

Co-authored-by: alfonso-aft <289616620+alfonso-aft@users.noreply.github.com>
A corrupt header is refused as schema drift by format validation before SQLite reads it. Assert that preserved cause. Create a distinct derived SQLite generation per measurement handshake so Unix preallocation cannot make a growing database's allocated-byte charge temporarily constant.

Co-authored-by: alfonso-aft <289616620+alfonso-aft@users.noreply.github.com>
The second historical Windows failure was not reproduced. Its loader/driver error spelling reveals an additional loss of classification: base-reference errors pass through registry I/O and driver strings, and view construction previously returned String. Preserve a stable busy prefix before the typed v3 error is erased, recognize the driver wrapper, and return CallgraphViewError from construction instead.

Test real SQLite contention through the ledger/driver wrapping and view construction, retaining permanent refusal behavior and verifying retry succeeds after the blocker closes. The readiness helper retains its 60-second cooperative deadline; no assertions or deadline were weakened.

Co-authored-by: alfonso-aft <289616620+alfonso-aft@users.noreply.github.com>
The exclusive-ledger construction regression ran red on both native Windows and Linux: initialization and validation swallowed SQLITE_BUSY and reported schema drift. Preserve contention at each lossy format/seed read while leaving all non-contention malformed/incomplete-schema decisions unchanged. Record the failed read, ledger path and SQLite cause.

Also account for the family-registry I/O wrapper before classifying driver errors. Add read-only validation coverage, including a successful reopen after the exclusive connection closes. These deterministic findings do not identify the cause of either historical CI incident.

Co-authored-by: alfonso-aft <289616620+alfonso-aft@users.noreply.github.com>
Co-authored-by: alfonso-aft <289616620+alfonso-aft@users.noreply.github.com>
@ualtinok
ualtinok added this pull request to the merge queue Oct 28, 2026
@ualtinok
ualtinok removed this pull request from the merge queue due to a manual request Oct 28, 2026
ualtinok and others added 3 commits October 29, 2026 01:24
Co-authored-by: alfonso-aft <289616620+alfonso-aft@users.noreply.github.com>
Mapping view contention to Building changed agent-visible answers:
callers lost "persisted callgraph store is busy" for a building
message, and inspect reported the view as not ready instead of pending.
The busy flag on base-completion contention is the actual fix; the
access keeps its SQLite busy form, which every caller already treats
as retryable.

Co-authored-by: alfonso-aft <289616620+alfonso-aft@users.noreply.github.com>
Co-authored-by: alfonso-aft <289616620+alfonso-aft@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant