diff --git a/broker/src/main/java/org/apache/rocketmq/broker/failover/EscapeBridge.java b/broker/src/main/java/org/apache/rocketmq/broker/failover/EscapeBridge.java index 84dcccaf750..c6a3a006f19 100644 --- a/broker/src/main/java/org/apache/rocketmq/broker/failover/EscapeBridge.java +++ b/broker/src/main/java/org/apache/rocketmq/broker/failover/EscapeBridge.java @@ -342,6 +342,7 @@ protected List decodeMsgList(GetMessageResult getMessageResult, bool List foundList = new ArrayList<>(); try { List messageBufferList = getMessageResult.getMessageBufferList(); + List messageQueueOffsets = getMessageResult.getMessageQueueOffset(); if (messageBufferList != null) { for (int i = 0; i < messageBufferList.size(); i++) { ByteBuffer bb = messageBufferList.get(i); @@ -354,8 +355,10 @@ protected List decodeMsgList(GetMessageResult getMessageResult, bool LOG.error("decode msgExt is null {}", getMessageResult); continue; } - // use CQ offset, not offset in Message - msgExt.setQueueOffset(getMessageResult.getMessageQueueOffset().get(i)); + // Use the CQ offset when the store supplied it; otherwise retain the decoded offset. + if (messageQueueOffsets != null && i < messageQueueOffsets.size()) { + msgExt.setQueueOffset(messageQueueOffsets.get(i)); + } foundList.add(msgExt); } } diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/PopReviveService.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/PopReviveService.java index 07f16e98965..e74f1f9d26f 100644 --- a/broker/src/main/java/org/apache/rocketmq/broker/processor/PopReviveService.java +++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/PopReviveService.java @@ -309,6 +309,7 @@ private List decodeMsgList(GetMessageResult getMessageResult, boolea List foundList = new ArrayList<>(); try { List messageBufferList = getMessageResult.getMessageBufferList(); + List messageQueueOffsets = getMessageResult.getMessageQueueOffset(); if (messageBufferList != null) { for (int i = 0; i < messageBufferList.size(); i++) { ByteBuffer bb = messageBufferList.get(i); @@ -322,7 +323,9 @@ private List decodeMsgList(GetMessageResult getMessageResult, boolea continue; } // use CQ offset, not offset in Message - msgExt.setQueueOffset(getMessageResult.getMessageQueueOffset().get(i)); + if (messageQueueOffsets != null && i < messageQueueOffsets.size()) { + msgExt.setQueueOffset(messageQueueOffsets.get(i)); + } foundList.add(msgExt); } } diff --git a/broker/src/test/java/org/apache/rocketmq/broker/failover/EscapeBridgeTest.java b/broker/src/test/java/org/apache/rocketmq/broker/failover/EscapeBridgeTest.java index 27fc37dbec8..de3ea23134c 100644 --- a/broker/src/test/java/org/apache/rocketmq/broker/failover/EscapeBridgeTest.java +++ b/broker/src/test/java/org/apache/rocketmq/broker/failover/EscapeBridgeTest.java @@ -353,6 +353,23 @@ public void decodeMsgListTest_messageNotNull() throws Exception { Assert.assertTrue(Arrays.equals(msg.getBody(), list.get(0).getBody())); } + @Test + public void decodeMsgListTest_messageOffsetMissing() throws Exception { + MessageExt msg = new MessageExt(); + msg.setBody("HW".getBytes()); + msg.setTopic("topic"); + msg.setBornHost(new InetSocketAddress("127.0.0.1", 9000)); + msg.setStoreHost(new InetSocketAddress("127.0.0.1", 9000)); + ByteBuffer byteBuffer = ByteBuffer.wrap(MessageDecoder.encode(msg, false)); + SelectMappedBufferResult result = new SelectMappedBufferResult(0, byteBuffer, 10, new DefaultMappedFile()); + + getMessageResult.addMessage(result); + + List list = escapeBridge.decodeMsgList(getMessageResult, false); + Assert.assertEquals(1, list.size()); + Assert.assertTrue(Arrays.equals(msg.getBody(), list.get(0).getBody())); + } + @Test public void testPutMessageToRemoteBroker_noSpecificBrokerName_hasRemoteBroker() throws Exception { MessageExtBrokerInner message = new MessageExtBrokerInner(); diff --git a/broker/src/test/java/org/apache/rocketmq/broker/processor/PopReviveServiceTest.java b/broker/src/test/java/org/apache/rocketmq/broker/processor/PopReviveServiceTest.java index fa7e9982e1f..a45f05896b0 100644 --- a/broker/src/test/java/org/apache/rocketmq/broker/processor/PopReviveServiceTest.java +++ b/broker/src/test/java/org/apache/rocketmq/broker/processor/PopReviveServiceTest.java @@ -38,9 +38,12 @@ import org.apache.rocketmq.remoting.protocol.subscription.SubscriptionGroupConfig; import org.apache.rocketmq.store.AppendMessageResult; import org.apache.rocketmq.store.AppendMessageStatus; +import org.apache.rocketmq.store.GetMessageResult; import org.apache.rocketmq.store.MessageStore; import org.apache.rocketmq.store.PutMessageResult; import org.apache.rocketmq.store.PutMessageStatus; +import org.apache.rocketmq.store.SelectMappedBufferResult; +import org.apache.rocketmq.store.logfile.DefaultMappedFile; import org.apache.rocketmq.store.pop.AckMsg; import org.apache.rocketmq.store.pop.BatchAckMsg; import org.apache.rocketmq.store.pop.PopCheckPoint; @@ -53,7 +56,10 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import java.lang.reflect.Method; +import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -137,6 +143,27 @@ public void before() { popReviveService.setShouldRunPopRevive(true); } + @Test + @SuppressWarnings("unchecked") + public void testDecodeMsgListWithoutQueueOffsets() throws Exception { + MessageExt message = new MessageExt(); + message.setBody("message".getBytes()); + message.setTopic(TOPIC); + message.setBornHost(new InetSocketAddress("127.0.0.1", 9000)); + message.setStoreHost(new InetSocketAddress("127.0.0.1", 9000)); + + GetMessageResult getMessageResult = new GetMessageResult(); + ByteBuffer buffer = ByteBuffer.wrap(MessageDecoder.encode(message, false)); + getMessageResult.addMessage(new SelectMappedBufferResult(0, buffer, buffer.remaining(), new DefaultMappedFile())); + + Method decodeMsgList = PopReviveService.class.getDeclaredMethod("decodeMsgList", GetMessageResult.class, boolean.class); + decodeMsgList.setAccessible(true); + List decodedMessages = (List) decodeMsgList.invoke(popReviveService, getMessageResult, false); + + Assert.assertEquals(1, decodedMessages.size()); + Assert.assertArrayEquals(message.getBody(), decodedMessages.get(0).getBody()); + } + @Test public void testWhenAckMoreThanCk() throws Throwable { brokerConfig.setEnableSkipLongAwaitingAck(true);