You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by ji...@apache.org on 2026/04/21 11:15:33 UTC

(rocketmq) branch develop updated: [ISSUE #10268] Fix incorrect time range file selection in IndexStoreService.queryAsync (#10269)

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

RongtongJin pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/rocketmq.git


The following commit(s) were added to refs/heads/develop by this push:
     new 94fbfcf342 [ISSUE #10268] Fix incorrect time range file selection in IndexStoreService.queryAsync (#10269)
94fbfcf342 is described below

commit 94fbfcf342fe13fce9cba4a6c31d052aaaf920e1
Author: lizhimins <70...@qq.com>
AuthorDate: Tue Apr 21 19:15:26 2026 +0800

    [ISSUE #10268] Fix incorrect time range file selection in IndexStoreService.queryAsync (#10269)
    
    Co-authored-by: lizhimins <li...@users.noreply.github.com>
---
 .../tieredstore/index/IndexStoreService.java       |  5 ++-
 .../tieredstore/index/IndexStoreServiceTest.java   | 37 ++++++++++++++++++++++
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/tieredstore/src/main/java/org/apache/rocketmq/tieredstore/index/IndexStoreService.java b/tieredstore/src/main/java/org/apache/rocketmq/tieredstore/index/IndexStoreService.java
index 132d2162f9..bf91e051ea 100644
--- a/tieredstore/src/main/java/org/apache/rocketmq/tieredstore/index/IndexStoreService.java
+++ b/tieredstore/src/main/java/org/apache/rocketmq/tieredstore/index/IndexStoreService.java
@@ -235,11 +235,14 @@ public class IndexStoreService extends ServiceThread implements IndexService {
         try {
             readWriteLock.readLock().lock();
             ConcurrentNavigableMap<Long, IndexFile> pendingMap =
-                this.timeStoreTable.subMap(beginTime, true, endTime, true);
+                this.timeStoreTable.headMap(endTime, true);
             List<CompletableFuture<Void>> futureList = new ArrayList<>(pendingMap.size());
             ConcurrentSkipListMap<String /* queueId-offset */, IndexItem> result = new ConcurrentSkipListMap<>();
 
             for (Map.Entry<Long, IndexFile> entry : pendingMap.descendingMap().entrySet()) {
+                if (entry.getValue().getEndTimestamp() < beginTime) {
+                    break;
+                }
                 CompletableFuture<Void> completableFuture = entry.getValue()
                     .queryAsync(topic, key, maxCount, beginTime, endTime)
                     .thenAccept(itemList -> itemList.forEach(indexItem -> {
diff --git a/tieredstore/src/test/java/org/apache/rocketmq/tieredstore/index/IndexStoreServiceTest.java b/tieredstore/src/test/java/org/apache/rocketmq/tieredstore/index/IndexStoreServiceTest.java
index 7b881ddd44..90b706a96f 100644
--- a/tieredstore/src/test/java/org/apache/rocketmq/tieredstore/index/IndexStoreServiceTest.java
+++ b/tieredstore/src/test/java/org/apache/rocketmq/tieredstore/index/IndexStoreServiceTest.java
@@ -351,4 +351,41 @@ public class IndexStoreServiceTest {
         executorService.shutdown();
         Assert.assertTrue(result.get());
     }
+
+    @Test
+    public void queryCrossFileBoundaryTest() throws InterruptedException, ExecutionException {
+        indexService = new IndexStoreService(fileAllocator, filePath);
+        indexService.start();
+
+        // Create first file with early beginTime
+        long file1Begin = System.currentTimeMillis();
+        for (int i = 0; i < storeConfig.getTieredStoreIndexFileMaxIndexNum() - 1; i++) {
+            indexService.putKey(TOPIC_NAME, TOPIC_ID, QUEUE_ID,
+                Collections.singleton("crossKey"), i * 100L, MESSAGE_SIZE, file1Begin + i * 1000);
+        }
+
+        // Create second file with later beginTime (beyond query range)
+        long file2Begin = System.currentTimeMillis() + 100_000;
+        indexService.createNewIndexFile(file2Begin);
+        for (int i = 0; i < 5; i++) {
+            indexService.putKey(TOPIC_NAME, TOPIC_ID, QUEUE_ID,
+                Collections.singleton("crossKey"), i * 100L, MESSAGE_SIZE, file2Begin + i);
+        }
+
+        Assert.assertEquals(2, indexService.getTimeStoreTable().size());
+
+        // Query range: beginTime is AFTER file1's beginTime but BEFORE file1's last item timestamp
+        // This should select file1, NOT file2 (file2 beginTime > queryEnd)
+        long queryBegin = file1Begin + 5_000;
+        long queryEnd = file1Begin + 15_000;
+
+        List<IndexItem> results = indexService.queryAsync(
+            TOPIC_NAME, "crossKey", 10, queryBegin, queryEnd).get();
+
+        // file1 has items at timestamps: file1Begin, file1Begin+1000, ..., file1Begin+(N-1)*1000
+        // Items in range [file1Begin+5000, file1Begin+15000] should match
+        // The bug (subMap) would return empty because file1's key < queryBegin
+        Assert.assertFalse("Should find index items from file covering query range", results.isEmpty());
+        Assert.assertTrue("Should find items within query time range", results.size() > 0);
+    }
 }
\ No newline at end of file