Skip to content

[fix][client] Return flow-control permit when client seek by messageID - #26726

Open
programmerahul wants to merge 3 commits into
apache:masterfrom
programmerahul:fix/chunked-message-seek-startmessageid-permit-leak
Open

programmerahul wants to merge 3 commits into
apache:masterfrom
programmerahul:fix/chunked-message-seek-startmessageid-permit-leak

Conversation

@programmerahul

@programmerahul programmerahul commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #26727

Motivation

When a consumer seeks to (or is created with) a specific startMessageId, the broker re-dispatches the boundary message, which the client filters out in messageReceived() via the isSameEntry(msgId) && isPriorEntryIndex(...) block. That block released the payload and returned without calling increaseAvailablePermits(), so the dropped message's outstanding flow-control permit was never repaid (it is not delivered, so messageProcessed() never runs for it).

Each seek-to-messageId therefore leaks one permit. It is masked at normal receiver queue sizes (seek re-establishes flow control), but with receiverQueueSize=1 the single leaked permit exhausts the whole budget and the consumer stalls immediately after the seek -- the message after the seek target is never delivered. Not chunking-specific; applies to plain messages too.

Modifications

return the permit in the drop block. Adds a test (plain messages, receiverQueueSize=1) that stalls without the fix and passes with it.

Verifying this change

  • Make sure that the change passes the CI checks.

(Please pick either of the following options)

This change added tests and can be verified as follows:

  • *Added test-case so that no permit leak while seek operation *

Does this pull request potentially affect one of the following parts:

If the box was checked, please highlight the changes

  • Dependencies (add or upgrade a dependency)
  • The public API
  • The schema
  • The default values of configurations
  • The threading model
  • The binary protocol
  • The REST endpoints
  • The admin CLI options
  • The metrics
  • Anything that affects deployment

…geId boundary message

When a consumer seeks to (or is created with) a specific startMessageId, the broker
re-dispatches the boundary message, which the client filters out in messageReceived()
via the `isSameEntry(msgId) && isPriorEntryIndex(...)` block. That block released the
payload and returned without calling increaseAvailablePermits(), so the dropped
message's outstanding flow-control permit was never repaid (it is not delivered, so
messageProcessed() never runs for it).

Each seek-to-messageId therefore leaks one permit. It is masked at normal receiver
queue sizes (seek re-establishes flow control), but with receiverQueueSize=1 the single
leaked permit exhausts the whole budget and the consumer stalls immediately after the
seek -- the message after the seek target is never delivered. Not chunking-specific;
applies to plain messages too.

Fix: return the permit in the drop block. Adds a test (plain messages,
receiverQueueSize=1) that stalls without the fix and passes with it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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] Return flow-control permit when client seek by messageID

1 participant