8000 fix(wal): never append after a torn WAL entry (#513) by adityamukho · Pull Request #514 · project-minigraf/minigraf · GitHub
[go: up one dir, main page]

Skip to content

fix(wal): never append after a torn WAL entry (#513) - #514

Merged
adityamukho merged 1 commit into
v3from
fix/513-wal-torn-tail
Oct 10, 2026
Merged

adityamukho merged 1 commit into
v3from
fix/513-wal-torn-tail

Conversation

@adityamukho
Copy link
Copy Markdown
Collaborator

Refs #513 (data-integrity: stays open until the fix is in a published release). Found while working on #390.

Problem

WAL replay stops at the first partial or damaged entry, but WalWriter appended at the end of the file. After a crash during an append, the next session's commits went in after the partial entry, so a second crash before any checkpoint lost them, although each was fsynced and reported committed. A failed append (short write, ENOSPC, EIO) in a running process did the same to the next commit through that handle. Reproduced on v3 and on main (v2.0.4).

Fix

  • WalWriter::open_or_create_at cuts an existing WAL back to the end of its last valid entry and syncs it before appending. The scan is shared with WalReader::read_entries (scan_entries).
  • After a failed write or sync, the writer refuses every later append with the new WAL-007. A checkpoint (which deletes the WAL) or a reopen gives a clean writer. Reads keep working. A rejected oversize fact (WAL-003) writes nothing and does not poison the writer.
  • The failed transaction is not applied in memory; after a reopen it is there in full or not at all (documented in ERROR_REFERENCE.md and Minigraf::execute).

This is the WAL part of the "mark the handle failed" rule; #390 extends it to checkpoints and adds the full fault matrix.

Tests

  • wal.rs: torn tail cut in the checksum, header and payload; a bad-checksum entry (and everything after it) cut off; an intact WAL left byte for byte; WAL-007 after a torn append (test-only tear_next_append hook); WAL-003 does not poison.
  • db.rs: through Minigraf, the failed transaction is not applied, transact and commit give WAL-007, and checkpoint() makes writes work again; facts survive reopen.
  • tests/wal_test.rs: a crashed child leaves a WAL; each torn-tail shape is appended; a second child commits and crashes; the reopen has both facts. Fails without the fix.

Docs: CHANGELOG, ERROR_REFERENCE (WAL-007), TEST_COVERAGE, test counts (1,393). Docs-site PR to follow. A v2.x backport PR to main will follow once this is merged.

🤖 Generated with Claude Code

https://claude.ai/code/session_012wXxZguv7PgKQjMMH4yJ5h

WAL replay stops at the first partial or damaged entry, but the writer
appended at the end of the file. After a crash during an append, the next
session's commits went in after the partial entry, so a second crash
before any checkpoint lost them although each was fsynced and reported
committed. A failed append in a running process did the same to the next
commit through that handle.

- WalWriter::open_or_create_at cuts an existing WAL back to the end of its
  last valid entry and syncs it before appending (scan_entries, shared
  with WalReader::read_entries).
- After a failed write or sync, the writer refuses every later append
  with the new WAL-007. A checkpoint (which deletes the WAL) or a reopen
  starts a clean writer. A rejected oversize fact (WAL-003) writes nothing
  and does not poison the writer.

Tests: WAL unit tests for each torn-tail shape, a bad-checksum entry, an
intact WAL left byte for byte, WAL-007 after a torn append (test-only
hook), and WAL-003 not poisoning; a Minigraf test for WAL-007 from
transact and commit and recovery by checkpoint; and a wal_test.rs
integration test that crashes a child after a torn tail and checks the
commit survives.

Refs #513

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wXxZguv7PgKQjMMH4yJ5h
@codecov
codecov Bot commented Oct 10, 2026
Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.87500% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/wal.rs 96.87% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

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

0