vacuum morsels: bound the leader's round consumption at the resume point (fixes #66) - #89
vacuum morsels: bound the leader's round consumption at the resume point (fixes #66)#89jdatcmd wants to merge 2 commits into
Conversation
…he rewound resume (issue malisper#66) A lost Local rewinds resume_g below granules other workers completed; the serial arm re-scans from there and re-collects the same LP_DEAD items. dead_items_add's num_items is add-not-replace, so every dead run and deferred blocking-cleanup page at/above the rewound resume point that the leader also consumes in the round double-counts dead tuples (debug: collect_dead_tids' assert trips; release: silent misreport). The test drives the exact issue scenario against the leader's round consumption as morsels.rs builds it today. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e resume point (issue malisper#66) New pure leader_round_work(locals, resume_bound): the dead runs merged into the round authority store and the deferred blocking-cleanup pages the leader processes, both filtered strictly below the resume point. morsels.rs computes the bound after the §5.2 coverage check (first serial-arm block, None on a completed round) and consumes only that — on a coverage rewind, at/above-bound work is left entirely to the serial re-scan, which re-collects the same LP_DEAD items exactly once. Filtering happens before the merge so an OverlapAt trip's duplicated block never meets the merge's disjointness contract. Healthy rounds carry nothing above the bound (ScannedBeyondResume is a coverage error), so this is behavior-neutral there — pinned by the unbounded parity sweep. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
Included review availability: Your plan provides up to 8 included reviews per hour; 5 remain after this review. 📝 WalkthroughWalkthroughThe vacuum leader now uses ChangesVacuum recovery filtering
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The change bounds leader work at the resume point and includes targeted regression coverage; no actionable merge-blocking risk remains after normal checks and review. Sequence Diagram(s)sequenceDiagram
participant VacuumMorsels
participant VacScanLocal
participant leader_round_work
participant SerialLeader
VacuumMorsels->>VacScanLocal: collect worker dead runs and deferred-cleanup blocks
VacuumMorsels->>leader_round_work: pass locals and resume bound
leader_round_work->>leader_round_work: filter entries below resume bound
leader_round_work->>SerialLeader: return sorted dead runs and cleanup blocks
SerialLeader->>VacuumMorsels: process retained entries during round finalization
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Fixes #66. Independent branch off main.
On a §5.2 coverage trip,
resume_grewinds below granules other workers already completed, and the serial arm re-scans from there. Re-pruning a pruned page re-collects the same LP_DEAD items, anddead_items_add'snum_itemsis add-not-replace — so anything the leader consumed from the round at/above the rewound resume point gets counted twice (debug:collect_dead_tids' assert trips; release: silent dead-tuple misreport into progress reporting and downstream decisions).The issue names the deferred blocking-cleanup pages; while fixing it I found the dead-run merge has the same exposure:
merge_dead_runsfolds all workers' runs unfiltered, so above-the-hole runs double-count identically once the serial arm re-prunes those blocks. Both are fixed with one bound.Changes
vacuum_morsels: new pureleader_round_work(locals, resume_bound)— the dead runs to merge into the round authority store and the deferred pages the leader processes, both filtered strictly below the resume point (Nonebound on a completed round). Filtering happens before the merge: on anOverlapAttrip the double-claimed block sits at/above the bound, and the merge's blocks-disjoint-across-Locals contract only holds for the below-bound remainder.vacuumlazymorsels.rs: the leader computes the bound right after the coverage check (block_of(resume_g), i.e. the first block the serial arm will visit) and consumes onlyleader_round_work's output. At/above-bound deferred pages are left to the serial arm's blocking-cleanup path, which the C body already handles — mirroring howskipsallvis_before(resume_g)already filters skip decisions at the resume point.ScannedBeyondResume, so nothing above the bound exists unless the guard tripped — pinned by a 200-case random parity sweep (leader_round_work(locals, None)≡merge_dead_runs+ raw ledger; any bound splits both consistently).Testing (TDD, red→green in the container)
431534b):coverage_trip_drops_round_work_above_the_rewound_resumedrives the issue's exact scenario — a lost Local holding lower granules (HoleAtrewind) while a surviving worker above the hole carries both a dead run and a deferred cleanup page — against the leader's round consumption as morsels.rs builds it today. Fails:dead runs at/above the resume point double-count num_items once the serial arm re-prunes them.leader_round_work; below-hole work is kept (the serial arm never revisits it), at/above-bound work is dropped. All 13vacuum_morselstests + thevacuumlazysuite pass. Ubuntu 26.04, rustc 1.96.0.🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests