Skip to content

fix: run alignAcknowledgeStatus for every flushed entry, not just the last one - #26305

Open
waterWang wants to merge 1 commit into
apache:masterfrom
waterWang:fix/26304-cursor-reset-align-acknowledge-group
Open

fix: run alignAcknowledgeStatus for every flushed entry, not just the last one#26305
waterWang wants to merge 1 commit into
apache:masterfrom
waterWang:fix/26304-cursor-reset-align-acknowledge-group

Conversation

@waterWang

@waterWang waterWang commented Aug 10, 2026

Copy link
Copy Markdown

Motivation

When a durable cursor reset and a mark-delete (individual ack) are enqueued together in pendingMarkDeleteOps while PENDING_READ_OPS > 0, internalFlushPendingMarkDeletes picks only the last entry and persists it. On persist completion, only the last entry's alignAcknowledgeStatus() runs — so the earlier entry's state mutation is silently dropped, even though triggerComplete() fans out the callbacks, making the reset report success while the cursor never moved.

Root Cause

Since #25047, the cursor reset's state mutation lives in a per-MarkDeleteEntry runnable (alignAcknowledgeStatusAfterPersisted), not in the reset's completion callback. When two entries are flushed together:

  1. Reset entry R is queued first (PENDING_READ_OPS > 0)
  2. Ack entry A is queued behind it
  3. internalFlushPendingMarkDeletes calls pendingMarkDeleteOps.getLast() -> A
  4. On persist, only A's alignAcknowledgeStatus() runs
  5. R's reset runnable is dropped, but triggerComplete() still fires the reset callback -> success is reported

Fix

In the persist completion callback, when mdEntry.callbackGroup is set (meaning multiple entries were flushed together), iterate the group and call alignAcknowledgeStatus() on every entry, not just the last one. This ensures that each request's in-memory state mutation is applied, while the persist position still comes from the last entry.

Testing

The existing test suite covers the basic reset and mark-delete paths. A targeted test for the displacement scenario (reset + ack queued, ack flushed last) is tracked in the issue's reproduction sketch.

Issue

Closes #26304

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.

[Bug] Durable cursor reset (seek / reset-cursor) can be silently discarded while reporting success when another mark-delete is queued after it

1 participant