From 8761644af158c5e7f05e999e9834b6496ce414e7 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期六, 29 八月 2026 16:04:31 +0800
Subject: [PATCH] 优化采集器长时历史的有界读取
---
ruoyi-device/src/test/java/com/ruoyi/device/contract/SimulatorPublicContractTest.java | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 112 insertions(+), 3 deletions(-)
diff --git a/ruoyi-device/src/test/java/com/ruoyi/device/contract/SimulatorPublicContractTest.java b/ruoyi-device/src/test/java/com/ruoyi/device/contract/SimulatorPublicContractTest.java
index 7a55294..4570d60 100644
--- a/ruoyi-device/src/test/java/com/ruoyi/device/contract/SimulatorPublicContractTest.java
+++ b/ruoyi-device/src/test/java/com/ruoyi/device/contract/SimulatorPublicContractTest.java
@@ -24,12 +24,14 @@
import com.ruoyi.device.simulator.BtsSimulatorStateStore.ChannelState;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorChannelState;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend;
+import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryBatch;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryFaults;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMetricState;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorState;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.DeviceState;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.SimulatorState;
+import com.ruoyi.device.simulator.BtsSimulatorStateStore.RecentRequest;
import com.ruoyi.device.simulator.InMemoryBtsSimulatorStateStore;
class SimulatorPublicContractTest
@@ -121,15 +123,28 @@
void collectorKeepsAppendOnlyHistoryBeyondPreviousDisplayLimit() throws Exception
{
Instant startedAt = Instant.parse("2026-08-29T03:00:00Z");
- try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
+ TrackingHistoryStore store = new TrackingHistoryStore();
+ try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, store))
{
simulator.configureCollectorSampling(1, 100, CollectorHistoryFaults.none());
simulator.advanceCollectors(startedAt);
for (int batch = 1; batch <= 5; batch++)
simulator.advanceCollectors(startedAt.plusMillis(batch * 100_000L));
- assertEquals(60_012, simulator.collectorHistory(1, 0, 1).total());
- assertEquals(1, simulator.collectorHistory(1, 0, 1).records().get(0).sequenceId());
+ store.resetReadStats();
+ var page = simulator.collectorHistory(1, 0, 1);
+ assertEquals(60_012, page.total());
+ assertEquals(1, page.records().get(0).sequenceId());
+ assertEquals(1, store.historyReads);
+ assertEquals(1, store.recordsRead);
+ }
+
+ store.resetReadStats();
+ try (BtsDevelopmentSimulator ignored = new BtsDevelopmentSimulator(0, store))
+ {
+ assertTrue(store.historyReads > 1);
+ assertEquals(1000, store.maximumRequestedLimit);
+ assertEquals(60_012, store.recordsRead);
}
}
@@ -480,4 +495,98 @@
assertThrows(IllegalStateException.class,
() -> new BtsDevelopmentSimulator(0, store));
}
+
+ @Test
+ void developmentSimulatorRejectsHistorySequenceRegressionAcrossPages()
+ {
+ Instant observedAt = Instant.parse("2026-08-29T06:30:00Z");
+ List<CollectorChannelState> channels = List.of(new CollectorChannelState("S-01", List.of(
+ new CollectorMetricState("temperature", new BigDecimal("25.0"), "℃"))));
+ List<CollectorMeasurementRecord> records = new java.util.ArrayList<>();
+ for (long sequence = 1; sequence <= 1000; sequence++)
+ records.add(new CollectorMeasurementRecord("dev-sim", "dev-sim-collector-1", "S-01", sequence,
+ observedAt, "2026-08-29 14:30:00.000", observedAt, "temperature",
+ new BigDecimal("25.0"), "℃"));
+ records.add(new CollectorMeasurementRecord("dev-sim", "dev-sim-collector-1", "S-01", 999,
+ observedAt, "2026-08-29 14:30:00.000", observedAt, "temperature",
+ new BigDecimal("25.0"), "℃"));
+ CollectorState collector = new CollectorState(1, "dev-sim-collector-1", "127.0.1.2",
+ "02:43:00:00:00:01", "模拟采集器", "开发模拟器", "Virtual Collector", 1, true,
+ 1000, 1001L, observedAt, channels, List.of(), records.size(), CollectorHistoryFaults.none());
+ SimulatorState damaged = new SimulatorState(BtsSimulatorStateStore.CURRENT_VERSION,
+ List.of(), List.of(collector), 1, 2, List.of());
+ InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore(damaged);
+ store.save(damaged, List.of(new CollectorHistoryAppend(collector.deviceCode(), records)));
+
+ assertThrows(IllegalStateException.class,
+ () -> new BtsDevelopmentSimulator(0, store));
+ }
+
+ private static final class TrackingHistoryStore implements BtsSimulatorStateStore
+ {
+ private final InMemoryBtsSimulatorStateStore delegate = new InMemoryBtsSimulatorStateStore();
+ private int historyReads;
+ private int maximumRequestedLimit;
+ private long recordsRead;
+
+ @Override
+ public SimulatorState loadOrInitialize(SimulatorState defaultState)
+ {
+ return delegate.loadOrInitialize(defaultState);
+ }
+
+ @Override
+ public void save(SimulatorState state)
+ {
+ delegate.save(state);
+ }
+
+ @Override
+ public void save(SimulatorState state, List<CollectorHistoryAppend> historyAppends)
+ {
+ delegate.save(state, historyAppends);
+ }
+
+ @Override
+ public CollectorHistoryBatch loadCollectorHistoryPage(String collectorCode, long offset, int limit,
+ boolean reverse)
+ {
+ CollectorHistoryBatch batch = delegate.loadCollectorHistoryPage(collectorCode, offset, limit, reverse);
+ historyReads++;
+ maximumRequestedLimit = Math.max(maximumRequestedLimit, limit);
+ recordsRead += batch.records().size();
+ return batch;
+ }
+
+ @Override
+ public void saveAndDeleteCollectorHistory(SimulatorState state, String collectorCode)
+ {
+ delegate.saveAndDeleteCollectorHistory(state, collectorCode);
+ }
+
+ @Override
+ public List<RecentRequest> loadRecentRequests()
+ {
+ return delegate.loadRecentRequests();
+ }
+
+ @Override
+ public void saveRecentRequests(List<RecentRequest> requests)
+ {
+ delegate.saveRecentRequests(requests);
+ }
+
+ @Override
+ public void reset(SimulatorState defaultState)
+ {
+ delegate.reset(defaultState);
+ }
+
+ private void resetReadStats()
+ {
+ historyReads = 0;
+ maximumRequestedLimit = 0;
+ recordsRead = 0;
+ }
+ }
}
--
Gitblit v1.7.1