This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git


The following commit(s) were added to refs/heads/dev by this push:
     new 6934fd0062 [Improve][Connector-V2] Note the multi-topic early return 
in currentOffsets (#12417)
6934fd0062 is described below

commit 6934fd00626e6347f86320b4f97d7c4cddc0fb59
Author: Sepuri Sai Krishna <[email protected]>
AuthorDate: Mon Sep 21 15:36:33 2026 +0000

    [Improve][Connector-V2] Note the multi-topic early return in currentOffsets 
(#12417)
---
 .../rocketmq/common/RocketMqAdminUtil.java         | 10 +++++
 .../rocketmq/common/RocketMqAdminUtilTest.java     | 43 ++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git 
a/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/common/RocketMqAdminUtil.java
 
b/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/common/RocketMqAdminUtil.java
index 589d917cbc..df164fe0d2 100644
--- 
a/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/common/RocketMqAdminUtil.java
+++ 
b/seatunnel-connectors-v2/connector-rocketmq/src/main/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/common/RocketMqAdminUtil.java
@@ -339,6 +339,16 @@ public class RocketMqAdminUtil {
                         && topicRouteAvailable(adminClient, topic)) {
                     // The retry topic is per group, not per topic, so this 
applies to every topic
                     // in the request and the whole lookup is legitimately 
empty.
+                    //
+                    // Returning here discards anything consumerOffsets has 
already collected for
+                    // earlier topics, and topics is a supported multi-topic 
list
+                    // (RocketMqSourceOptions.TOPICS). That is safe only under 
the invariant
+                    // above: a group cannot commit an offset for any topic 
without first
+                    // registering, and registering is what creates the retry 
topic, so a missing
+                    // retry topic means no topic in the list has committed 
anything and the map
+                    // is necessarily still empty here. If that ever stops 
holding, this has to
+                    // become a continue that keeps the earlier offsets, 
otherwise a later
+                    // cold-start topic silently rewinds the topics already 
read.
                     log.warn(
                             "Consumer group {} has no retry topic yet, so it 
has never registered "
                                     + "and has committed nothing. Topic {} 
still resolves, so this "
diff --git 
a/seatunnel-connectors-v2/connector-rocketmq/src/test/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/common/RocketMqAdminUtilTest.java
 
b/seatunnel-connectors-v2/connector-rocketmq/src/test/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/common/RocketMqAdminUtilTest.java
index daae2bbcc7..6072ddc389 100644
--- 
a/seatunnel-connectors-v2/connector-rocketmq/src/test/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/common/RocketMqAdminUtilTest.java
+++ 
b/seatunnel-connectors-v2/connector-rocketmq/src/test/java/org/apache/seatunnel/connectors/seatunnel/rocketmq/common/RocketMqAdminUtilTest.java
@@ -31,8 +31,10 @@ import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 
 /**
@@ -50,6 +52,7 @@ class RocketMqAdminUtilTest {
 
     private static final String GROUP = "test-group";
     private static final String TOPIC = "test-topic";
+    private static final String OTHER_TOPIC = "other-test-topic";
 
     /**
      * A group that has never registered has no retry topic, so the lookup 
fails with
@@ -193,4 +196,44 @@ class RocketMqAdminUtilTest {
 
         Assertions.assertEquals(Collections.singletonMap(messageQueue, 42L), 
offsets);
     }
+
+    /**
+     * RocketMqSourceOptions.TOPICS accepts a comma separated list, so the 
lookup loops over several
+     * topics and merges their consume stats. Pinning that here keeps the loop 
from being rewritten
+     * into one that returns the first topic's offsets and drops the rest.
+     */
+    @Test
+    void testCurrentOffsets_multipleTopicsAreMergedAcrossTheLoop() throws 
Exception {
+        MessageQueue firstQueue = new MessageQueue(TOPIC, "broker-a", 0);
+        MessageQueue secondQueue = new MessageQueue(OTHER_TOPIC, "broker-a", 
0);
+
+        DefaultMQAdminExt adminClient = Mockito.mock(DefaultMQAdminExt.class);
+        Mockito.when(adminClient.examineConsumeStats(GROUP, TOPIC))
+                .thenReturn(consumeStatsFor(firstQueue, 42L));
+        Mockito.when(adminClient.examineConsumeStats(GROUP, OTHER_TOPIC))
+                .thenReturn(consumeStatsFor(secondQueue, 7L));
+
+        Map<MessageQueue, Long> offsets =
+                RocketMqAdminUtil.currentOffsets(
+                        adminClient,
+                        GROUP,
+                        Arrays.asList(TOPIC, OTHER_TOPIC),
+                        new HashSet<>(Arrays.asList(firstQueue, secondQueue)));
+
+        Map<MessageQueue, Long> expected = new HashMap<>();
+        expected.put(firstQueue, 42L);
+        expected.put(secondQueue, 7L);
+        Assertions.assertEquals(expected, offsets);
+    }
+
+    private static ConsumeStats consumeStatsFor(MessageQueue messageQueue, 
long committedOffset) {
+        OffsetWrapper offsetWrapper = new OffsetWrapper();
+        offsetWrapper.setConsumerOffset(committedOffset);
+        HashMap<MessageQueue, OffsetWrapper> offsetTable = new HashMap<>();
+        offsetTable.put(messageQueue, offsetWrapper);
+
+        ConsumeStats consumeStats = new ConsumeStats();
+        consumeStats.setOffsetTable(offsetTable);
+        return consumeStats;
+    }
 }

Reply via email to