lhotari commented on code in PR #26135:
URL: https://github.com/apache/pulsar/pull/26135#discussion_r3519698434


##########
pulsar-client/src/test/java/org/apache/pulsar/client/impl/ConsumerImplTest.java:
##########
@@ -341,4 +351,49 @@ public void 
testUpdateAutoScaleReceiverQueueHintRaceWithConcurrentDrain() {
                 "Hint must reflect the post-enqueue state (pipeline had >=1 
message); "
                         + "a concurrent drain of the just-enqueued message 
must not clear it.");
     }
+
+    @Test(invocationTimeOut = 1000)
+    public void testGetMessageAtSyncsAckSetInMessageIdWithBrokerAckSet() {
+        // Regression test for MessagePayloadContextImpl#getMessageAt: the 
BatchMessageIdImpl handed
+        // back to the caller carries a shared ackSetInMessageId bitset that 
must be seeded from the
+        // broker-reported ackSet, not a fresh "all unacked" bitset. Otherwise 
indices the broker
+        // already knows are acked would be reported as still-outstanding in 
the returned MessageId,
+        // which is the same root cause that let acked batch messages leak 
into the DLQ (see
+        // ConsumerImpl#receiveIndividualMessagesFromBatch and its 
ackSetInMessageId.and(...) fix).
+        final int batchSize = 3;
+        MessageMetadata messageMetadata = new MessageMetadata()
+                .setProducerName("test-producer")
+                .setSequenceId(0)
+                .setPublishTime(System.currentTimeMillis())
+                .setNumMessagesInBatch(batchSize);
+
+        // Broker reports index 0 as already acked (bit cleared); indices 1 
and 2 are still
+        // outstanding (bits set). This mirrors the ackSet the broker attaches 
on redelivery.
+        BitSet brokerAckSet = new BitSet(batchSize);
+        brokerAckSet.set(1);
+        brokerAckSet.set(2);
+        List<Long> ackSet = 
Arrays.stream(brokerAckSet.toLongArray()).boxed().collect(Collectors.toList());
+
+        MessageIdImpl messageId = new MessageIdImpl(1L, 2L, -1);
+        MessagePayloadContextImpl context = MessagePayloadContextImpl.get(
+                null, messageMetadata, messageId, consumer, 0, ackSet, 
DEFAULT_CONSUMER_EPOCH);
+        try {
+            // Index 0 is already acked per the broker, so it must not be 
redelivered to the app.
+            MessagePayload payload0 = 
MessagePayloadImpl.create(Unpooled.wrappedBuffer(new byte[]{0}));
+            Assert.assertNull(context.getMessageAt(0, batchSize, payload0, 
false, Schema.BYTES));
+
+            MessagePayload payload1 = 
MessagePayloadImpl.create(Unpooled.wrappedBuffer(new byte[]{1}));
+            Message<byte[]> message1 = context.getMessageAt(1, batchSize, 
payload1, false, Schema.BYTES);
+            Assert.assertNotNull(message1);

Review Comment:
   Could use `@Cleanup("release")` for both `MessagePayload` instances to avoid 
the leak that @void-ptr974 pointed out.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to