Summary
When a merger implementing base.DeletableValueMerger returns delete=true from DeletableFinish during a compaction, the compaction iterator's needDelete handling elides the merge result via continue without performing the skip/position bookkeeping that the normal returned-key path performs. Depending on arrangement this causes either:
- Silent data corruption: the just-consumed base SET (and any older same-key entries the pending skip was supposed to elide) are re-processed as fresh keys, resurrecting a value for a key the merger declared non-existent; or
- A panic: compaction iterator has skip=true, but iterator is at iterPosNext on a subsequent Iter.Next() call.
Reproduced on v2.1.4, v2.1.5, v2.1.6; the relevant code is unchanged on master.
Jira issue: PEBBLE-1469
Summary
When a merger implementing
base.DeletableValueMergerreturnsdelete=truefromDeletableFinishduring a compaction, the compaction iterator'sneedDeletehandling elides the merge result viacontinuewithout performing theskip/positionbookkeeping that the normal returned-key path performs. Depending on arrangement this causes either:Reproduced on
v2.1.4,v2.1.5,v2.1.6; the relevant code is unchanged on master.Jira issue: PEBBLE-1469