Skip to content

Preserve overflow data across rollback and add recovery model tests - #249

Merged
zvndev merged 6 commits into
mainfrom
codex/powdb-recovery-model
Oct 8, 2026
Merged

zvndev merged 6 commits into
mainfrom
codex/powdb-recovery-model

Conversation

@zvndev

@zvndev zvndev commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Stacked on #248. Base: codex/powdb-integrity-milestone. Review only this incremental diff.

Add deterministic mixed-mutation/reopen testing against an independent model. It found two additional recovery defects, fixed with 15 production-code lines:

  • Retiring a catalog during rollback no longer checkpoints/truncates the replacement catalog's WAL after overflow cleanup has written to it.
  • Replayed overflow writes reserve their pages before the LSN guard, including when the physical bytes are already durable, so later inserts cannot overwrite committed payloads.

These fixes should ship with #248 as one release set. Neither PR is merged or released by this change.

Type of change

  • Bug fix
  • Documentation
  • CI / tooling

Behavior change

Repeated overflow-write/rollback sequences preserve committed data and a usable WAL. No new disk format, wire behavior, dependency, or automatic repair.

The normal test suite now exercises four deterministic seeds across three WAL modes and optimized/generic execution. It checks full rows, live counts, real unique/nonunique B-tree entries, dependent views, and graceful reopen. Every trace covers INSERT/UPSERT/UPDATE/DELETE, late uniqueness failures, explicit commit/rollback and aborted transactions. Replay instructions are in docs/recovery-testing.md.

CI also runs for stacked PRs targeting codex/**. The existing nightly/manual fuzz workflow runs a larger bounded model corpus and retains its operation traces for 14 days.

Test plan

  • Full Linux arm64 workspace: 2,685 passed, zero failures, 203 targets; five existing ignores unchanged.
  • Default disk-backed model corpus: 768 modeled steps, plus both focused regression cases.
  • Extended corpus: 18,432 modeled steps, plus focused regressions; zero failures.
  • Both reduced regressions failed before their fixes.
  • Mutation control: deliberately replaced failed-statement rollback with commit in a disposable source copy. The model caught the leaked row at seed 24301, step 3. Restored and recompiled correct sources before final verification.
  • Invalid corpus size zero fails rather than silently skipping testing.
  • Strict Clippy, rustfmt, warnings-as-errors rustdoc, actionlint, version/CI-needs/tool-pin guards and redacted gitleaks.
  • Independent code/spec review; new tests and replay documentation included; private tracking documents excluded.
  • GitHub's two-OS/sanitizer/compatibility gates on this stacked head: pending.

Limits

The larger Linux corpus uses /dev/shm to bound runtime; it proves logical-state/graceful-reopen behavior, not physical-disk or power-loss durability. Existing process-kill and fsync-failure suites remain separate and passed in the workspace run. This is a bounded addition to recovery coverage, not a complete storage/DDL fault matrix or an arbitrary-corrupted-file repair feature. No throughput gain is claimed.

Related issues

Depends on #248. After that PR merges, retarget this PR to main and rerun required checks before the release.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Unify mutation completion and aborted-transaction handling across engine and
client entry points. Preserve rollback in every WAL mode and distinguish
uncertain commits from ordinary statement failures. Add crash and fsync proofs,
explicit correlated bindings, view failure guards, and patched TLS dependencies.

Constraint: Preserve existing disk formats and numeric wire error classes.
Rejected: Treat a missing COMMIT reply as rollback | the durable outcome can be unknown.
Confidence: high
Scope-risk: broad
Directive: Keep internal BEGIN markers even without a separate fsync; legacy replay accepts boundary-free logs.
Tested: Linux instrumented workspace 2682 passed, strict Clippy/rustdoc, TS and Node suites, package smoke, audit/deny/gitleaks, Criterion execution smoke.
Not-tested: Actual power loss, full cross-file DDL fault matrix, authoritative Depot performance gate; WAL-Off write overhead is explicitly accepted and documented.
A seeded mutation model exposed two recovery interactions: dropping a retired
catalog truncated the replacement writer's WAL, and LSN-skipped overflow writes
left reused pages allocatable. Retire the old handle without checkpointing and
reserve replayed pages before the physical-write guard.

Constraint: Keep existing disk formats, wire behavior, and dependencies unchanged.
Rejected: Skip already-durable overflow records entirely | their allocation bookkeeping must still replay.
Confidence: high
Scope-risk: moderate
Directive: A retired catalog must not checkpoint; overflow allocation state precedes the replay LSN guard.
Tested: Linux workspace 2685 passed; 18432 modeled mutation steps; both reduced regressions failed before fixes; deliberately disabled rollback was detected; Clippy, rustdoc, format, actionlint, gitleaks.
Not-tested: Physical power loss and the complete storage fault matrix; larger corpus uses disclosed tmpfs for logical-state testing.
zvndev added 2 commits October 7, 2026 07:34
Preserve the reviewed correctness fixes while carrying forward current
compiler/Miri compatibility and the published-site analytics integration.

Constraint: Strict branch protection requires the candidate to include current main
Confidence: high
Scope-risk: moderate
Tested: Previously green independent branches; fresh combined CI follows this merge
Not-tested: Fresh merged CI until pushed
Constraint: Validate the stack against current main without rewriting history

Confidence: high
Scope-risk: moderate
Tested: Fresh combined CI will run after push
zvndev added 2 commits October 7, 2026 08:24
…ffer

Relieve prior committed dirty pages before the next implicit rollback pin.
Settle WAL generations before writing heap/header/index state, retain the WAL
history, and leave explicit transaction admission unchanged.

Constraint: Preserve statement rollback, retained history and deferred durability
Rejected: Raise the budget or cap the benchmark fixture | That would hide a real long-lived autocommit failure
Confidence: high
Scope-risk: moderate
Tested: Six query regressions after three failing-first cases; all WAL modes; prior-row preservation; deferred claims and retained history; 16 atomicity/durability tests; 257 storage unit tests; independent code review; fmt/diff checks
Not-tested: Fresh authoritative Depot rerun and combined CI pending
…tack

Confidence: high
Scope-risk: narrow
Tested: Six fresh regressions on the integrity base; combined CI follows
@zvndev
zvndev changed the base branch from codex/powdb-integrity-milestone to main October 8, 2026 19:21
@zvndev
zvndev merged commit 6cb9402 into main Oct 8, 2026
44 checks passed
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