From 370ef4f5e663fdfc1d19d2774dfc4ec1ed0af60e Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期六, 29 八月 2026 14:57:48 +0800
Subject: [PATCH] 修复采集器历史状态持续序列化错误
---
ruoyi-device/src/test/java/com/ruoyi/device/contract/SimulatorPublicContractTest.java | 79 ++++++++++++++++++++++++++++++++++-----
1 files changed, 69 insertions(+), 10 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 ba19503..7a55294 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
@@ -11,6 +11,7 @@
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Test;
+import com.alibaba.fastjson2.JSON;
import com.ruoyi.device.api.DeviceAdapter;
import com.ruoyi.device.bts.BtsDevelopmentSimulator;
import com.ruoyi.device.bts.BtsDeviceAdapter;
@@ -22,6 +23,7 @@
import com.ruoyi.device.simulator.BtsSimulatorStateStore;
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.CollectorHistoryFaults;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord;
import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMetricState;
@@ -132,6 +134,20 @@
}
@Test
+ void collectorRawHistoryIsNotEmbeddedInMainSimulatorState() throws Exception
+ {
+ InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore();
+ try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, store))
+ {
+ simulator.advanceCollectors(Instant.parse("2026-08-29T03:30:00Z"));
+
+ String mainState = JSON.toJSONString(store.loadOrInitialize(null));
+ assertFalse(mainState.contains("\"history\":[{"));
+ assertEquals(12, simulator.collectorHistory(1, 0, 100).total());
+ }
+ }
+
+ @Test
void collectorRealtimeDropsMeasurementsRemovedFromCurrentConfiguration() throws Exception
{
Instant startedAt = Instant.parse("2026-08-29T04:00:00Z");
@@ -159,6 +175,18 @@
{
assertEquals(4, restored.snapshot().collectors().get(0).latestMeasurements().size());
assertEquals(12, restored.collectorHistory(1, 0, 100).total());
+ }
+ }
+
+ @Test
+ void collectorRejectsMetricWhitespaceThatWouldBreakRestore() throws Exception
+ {
+ try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0))
+ {
+ assertThrows(IllegalArgumentException.class, () -> simulator.configureCollectorChannel(1, "S-01",
+ List.of(new CollectorMetricState("temperature ", new BigDecimal("25.0"), "℃"))));
+ assertThrows(IllegalArgumentException.class, () -> simulator.configureCollectorChannel(1, "S-01",
+ List.of(new CollectorMetricState("temperature", new BigDecimal("25.0"), " ℃"))));
}
}
@@ -347,6 +375,31 @@
}
@Test
+ void collectorDeletionDoesNotReplaceMemoryWhenAtomicPersistenceFails() throws Exception
+ {
+ InMemoryBtsSimulatorStateStore delegate = new InMemoryBtsSimulatorStateStore();
+ BtsSimulatorStateStore failing = new BtsSimulatorStateStore()
+ {
+ @Override public SimulatorState loadOrInitialize(SimulatorState value)
+ { return delegate.loadOrInitialize(value); }
+ @Override public void save(SimulatorState value) { delegate.save(value); }
+ @Override public void saveAndDeleteCollectorHistory(SimulatorState value, String collectorCode)
+ { throw new IllegalStateException("redis unavailable"); }
+ @Override public java.util.List<RecentRequest> loadRecentRequests()
+ { return delegate.loadRecentRequests(); }
+ @Override public void saveRecentRequests(java.util.List<RecentRequest> requests)
+ { delegate.saveRecentRequests(requests); }
+ @Override public void reset(SimulatorState value) { delegate.reset(value); }
+ };
+
+ try (BtsDevelopmentSimulator simulator = new BtsDevelopmentSimulator(0, failing))
+ {
+ assertThrows(IllegalStateException.class, () -> simulator.deleteCollector(1));
+ assertEquals(1, simulator.snapshot().collectors().size());
+ }
+ }
+
+ @Test
void developmentSimulatorRestoresUnfinishedTombstones() throws Exception
{
InMemoryBtsSimulatorStateStore store = new InMemoryBtsSimulatorStateStore();
@@ -390,17 +443,20 @@
Instant observedAt = Instant.parse("2026-08-29T05:00:00Z");
List<CollectorChannelState> channels = List.of(new CollectorChannelState("S-01", List.of(
new CollectorMetricState("temperature", new BigDecimal("25.0"), "℃"))));
+ CollectorMeasurementRecord record = new CollectorMeasurementRecord(
+ "dev-sim", "wrong-collector", "S-01", 1L, observedAt,
+ "2026-08-29 13:00: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, 2L, observedAt, channels, List.of(), List.of(new CollectorMeasurementRecord(
- "dev-sim", "wrong-collector", "S-01", 1L, observedAt,
- "2026-08-29 13:00:00.000", observedAt, "temperature",
- new BigDecimal("25.0"), "℃")), CollectorHistoryFaults.none());
+ 1000, 2L, observedAt, channels, List.of(), 1L, 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(), List.of(record))));
assertThrows(IllegalStateException.class,
- () -> new BtsDevelopmentSimulator(0, new InMemoryBtsSimulatorStateStore(damaged)));
+ () -> new BtsDevelopmentSimulator(0, store));
}
@Test
@@ -409,16 +465,19 @@
Instant observedAt = Instant.parse("2026-08-29T06:00:00Z");
List<CollectorChannelState> channels = List.of(new CollectorChannelState("S-01", List.of(
new CollectorMetricState("temperature", new BigDecimal("25.0"), "℃"))));
+ CollectorMeasurementRecord record = new CollectorMeasurementRecord(
+ "dev-sim", "dev-sim-collector-1", "S-01", 1L, observedAt,
+ "2026-08-29 14:00: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, 1L, observedAt, channels, List.of(), List.of(new CollectorMeasurementRecord(
- "dev-sim", "dev-sim-collector-1", "S-01", 1L, observedAt,
- "2026-08-29 14:00:00.000", observedAt, "temperature",
- new BigDecimal("25.0"), "℃")), CollectorHistoryFaults.none());
+ 1000, 1L, observedAt, channels, List.of(), 1L, 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(), List.of(record))));
assertThrows(IllegalStateException.class,
- () -> new BtsDevelopmentSimulator(0, new InMemoryBtsSimulatorStateStore(damaged)));
+ () -> new BtsDevelopmentSimulator(0, store));
}
}
--
Gitblit v1.7.1