[fix][client] Support nack, ackTimeout redelivery and dlq for chunked messages#604
Open
geniusjoe wants to merge 1 commit into
Open
[fix][client] Support nack, ackTimeout redelivery and dlq for chunked messages#604geniusjoe wants to merge 1 commit into
geniusjoe wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Prior to this change, the C++ client did not properly handle chunked messages in the following scenarios:
ChunkMessageIdwas nacked, without expanding all chunk entries. The broker would only redeliver the last chunk entry, making it impossible for the consumer to reassemble the complete message.UnAckedMessageTrackercalleddiscardBatch()onChunkMessageIdImpl, which created a new plainMessageIdImpland lost all internal chunk entry information. When ack timeout triggered, the tracker could not expand chunk entries for redelivery.This aligns the C++ client behavior with the Go and Java clients, which already handle these scenarios correctly.
Modifications
lib/ConsumerImpl.ccnegativeAcknowledge()— When the MessageId is aChunkMessageIdImpl, expand all chunk entries viagetChunkedMessageIds()and add each one individually tonegativeAcksTracker_. This ensures the broker redelivers all chunks.redeliverMessages()— Before sendingRedeliverUnacknowledgedMessagesto the broker, expand anyChunkMessageIdImplin the input set into all its chunk entries. This is the path triggered by ack timeout.DLQ producer configuration — Enable
setChunkingEnabled(true)for the DLQ producer so that large messages can be correctly chunked when sent to the DLQ topic.lib/UnAckedMessageTrackerEnabled.ccadd()method — SkipdiscardBatch()forChunkMessageIdImpl.discardBatch()creates a new plainMessageIdImpl, which would lose thechunkedMessageIds_vector stored insideChunkMessageIdImpl. By preserving the original object, when ack timeout triggers and the MessageId is passed toredeliverMessages(), it can be dynamically cast back toChunkMessageIdImpland expanded into all chunk entries.remove()method — Apply the same logic asadd()to ensure consistent key lookup and removal from the tracker.tests/MessageChunkingTest.cctestNegativeAckChunkedMessage— Verifies that a chunked message can be correctly redelivered after nack (aligned with GoTestChunkAckAndNAckand JavatestNegativeAckChunkedMessage).testAckTimeoutChunkedMessage— Verifies that a chunked message can be correctly redelivered after ack timeout (aligned with JavatestLargeMessageAckTimeOut).testChunkedMessageDLQ— Verifies that a chunked message is correctly sent to the DLQ topic after exceedingmaxRedeliverCount, with complete message content and correctPROPERTY_ORIGIN_MESSAGE_IDandSYSTEM_PROPERTY_REAL_TOPICproperties.Design Details
Why skip
discardBatch()forChunkMessageIdImpl?discardBatch()creates a newMessageIdImplretaining onlyledgerId,entryId, andpartitionIndex, discardingbatchIndexandbatchSize. ForChunkMessageIdImpl(a subclass ofMessageIdImpl), this would also lose thechunkedMessageIds_vector that stores all chunk entry positions. Without this information, the client cannot expand chunk entries for redelivery when ack timeout fires.Note:
ChunkMessageIdImplalready hasbatchIndex = -1(chunked messages are not batched), so skippingdiscardBatch()does not affect the key normalization purpose (deduplicating batch sub-entries in the tracker).Broker perspective
The broker does not recognize chunk message semantics. Each chunk is an independent entry in the managed ledger. The client is responsible for expanding all chunk entries when requesting redelivery, so the broker can replay all positions belonging to the same chunked message.
Comparison with Go and Java clients
ChunkMessageIdImpl.chunkedMessageIds_unAckedChunkedMessageIdSequenceMapunAckChunksTrackernegativeAcknowledge()entryNegativeAcksTrackertimeoutNackID()entryredeliverMessages()UnAckedMessageTrackertimeout callbackdynamic_pointer_castcheckinstanceof ChunkMessageIdImplchecksetChunkingEnabled(true)chunkingEnabled(true)WithChunking(true)All three clients achieve the same result: expand all chunk entries and send them to the broker for complete redelivery.
Local workflow
geniusjoe#2
