From 8761644af158c5e7f05e999e9834b6496ce414e7 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期六, 29 八月 2026 16:04:31 +0800
Subject: [PATCH] 优化采集器长时历史的有界读取

---
 ruoyi-admin/src/test/java/com/ruoyi/config/RedisStateStoreTest.java |   46 ++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/ruoyi-admin/src/test/java/com/ruoyi/config/RedisStateStoreTest.java b/ruoyi-admin/src/test/java/com/ruoyi/config/RedisStateStoreTest.java
index d9fad0c..dc22f33 100644
--- a/ruoyi-admin/src/test/java/com/ruoyi/config/RedisStateStoreTest.java
+++ b/ruoyi-admin/src/test/java/com/ruoyi/config/RedisStateStoreTest.java
@@ -5,7 +5,9 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
@@ -115,7 +117,8 @@
         SimulatorState restored = store.loadOrInitialize(state(1, "127.0.0.2"));
 
         assertEquals(1L, restored.collectors().get(0).historyRecordCount());
-        assertEquals(1, store.loadCollectorHistory("dev-sim-collector-1").size());
+        assertEquals(1, store.loadCollectorHistoryPage("dev-sim-collector-1", 0, 1000, false)
+                .records().size());
         assertEquals(true, stored.get().toString().contains("\"history\":[{"));
         store.completeValidatedRestore(restored);
         assertEquals(false, stored.get().toString().contains("\"history\":[{"));
@@ -182,7 +185,36 @@
         store.saveAndDeleteCollectorHistory(next, "dev-sim-collector-1");
 
         assertEquals(next, store.loadOrInitialize(current));
-        assertEquals(List.of(), store.loadCollectorHistory("dev-sim-collector-1"));
+        assertEquals(List.of(), store.loadCollectorHistoryPage("dev-sim-collector-1", 0, 1000, false)
+                .records());
+    }
+
+    @Test
+    void readsOnlyRequestedCollectorHistoryRange()
+    {
+        AtomicReference<Object> stored = new AtomicReference<>();
+        RedisTemplate<Object, Object> redis = redis(stored);
+        RedisBtsSimulatorStateStore store = new RedisBtsSimulatorStateStore(redis);
+        SimulatorState current = state(1, "127.0.0.2");
+        store.loadOrInitialize(current);
+        var record = new com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord(
+                "dev-sim", "dev-sim-collector-1", "S-01", 1L,
+                java.time.Instant.parse("2026-08-29T05:00:00Z"), "2026-08-29 13:00:00.000",
+                java.time.Instant.parse("2026-08-29T05:00:00Z"), "temperature",
+                new java.math.BigDecimal("25.1"), "℃");
+        store.save(current, List.of(
+                new com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend(
+                        "dev-sim-collector-1", java.util.Collections.nCopies(1010, record))));
+        ListOperations<Object, Object> lists = redis.opsForList();
+        clearInvocations(lists);
+
+        var page = store.loadCollectorHistoryPage("dev-sim-collector-1", 1000, 10, false);
+
+        assertEquals(1010, page.total());
+        assertEquals(10, page.records().size());
+        assertEquals(false, page.hasMore());
+        verify(lists).range(RedisBtsSimulatorStateStore.HISTORY_KEY_PREFIX + "dev-sim-collector-1",
+                1000L, 1009L);
     }
 
     @Test
@@ -290,8 +322,14 @@
                     listValues.put(key, records);
                     return (long) records.size();
                 });
-        when(lists.range(any(), anyLong(), anyLong())).thenAnswer(invocation ->
-                List.copyOf(listValues.getOrDefault(invocation.getArgument(0), List.of())));
+        when(lists.range(any(), anyLong(), anyLong())).thenAnswer(invocation -> {
+            List<Object> records = listValues.getOrDefault(invocation.getArgument(0), List.of());
+            long requestedStart = invocation.getArgument(1);
+            long requestedEnd = invocation.getArgument(2);
+            int start = (int) Math.min(requestedStart, records.size());
+            int end = (int) Math.min(requestedEnd + 1, records.size());
+            return start >= end ? List.of() : List.copyOf(records.subList(start, end));
+        });
         when(lists.size(any())).thenAnswer(invocation ->
                 (long) listValues.getOrDefault(invocation.getArgument(0), List.of()).size());
         when(redis.delete(org.mockito.ArgumentMatchers.<Object>any()))

--
Gitblit v1.7.1