From 4eaa4be4d2cbd2aa49d36a313ce71ad3e743db4a Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期三, 02 九月 2026 12:22:53 +0800
Subject: [PATCH] 彻底清理补采完整性遗留依赖
---
ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsDevelopmentSimulator.java | 2
scripts/clear-development-data.sql | 7 ---
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TTestLiveController.java | 2
ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/DeviceDiscoveryPersistenceServiceTest.java | 1
ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml | 19 ---------
ruoyi-admin/src/main/resources/db/migration/V28__remove_reception_backfill_integrity_legacy.sql | 2 +
ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsXmlCodec.java | 2
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java | 23 +----------
/dev/null | 25 ------------
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestServiceImpl.java | 4 +-
AGENTS.md | 9 ++--
ruoyi-admin/src/test/java/com/ruoyi/config/Ticket28MigrationContractTest.java | 2 +
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TestDataReceptionServiceImpl.java | 2
13 files changed, 16 insertions(+), 84 deletions(-)
diff --git a/AGENTS.md b/AGENTS.md
index 4108b24..126c165 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -12,9 +12,8 @@
## 设备路径
- 每个设备适配器实例从数据库读取名称、类型、主机、端口、启停、轮询周期、时区和能力,不在代码中固定连接参数。
-- 每个实例只有一个串行请求队列;一次 `inquire` 批量查询需监测通道。状态查询默认每 5 秒,历史下载使用较低优先级。
-- 连接拒绝、最长约 30 秒响应超时、断线和后端重启均进入对账与恢复流程。恢复时重新查询设备事实并从持久化游标补采,不推断设备已停止。
-- 历史补采按测试结束时间和通道公平轮转,每批最多 1000 条;数据保存成功后才推进数据库游标。
+- 每个实例只有一个串行请求队列;一次 `inquire` 批量查询需监测通道。状态查询默认每 5 秒。
+- 连接拒绝、响应超时、断线和后端重启只记录设备/请求异常并继续观测,不自动恢复或追回历史数据。
- 解析器拒绝 DOCTYPE/外部实体,限制响应大小,并显式处理缺字段、非法数值和未知枚举。
- 协议报文压缩保存到文件系统,数据库仅保存索引、校验值和解析结果;普通报文保留 30 天,解析失败或冲突报文保留 180 天。
@@ -22,7 +21,7 @@
- 开始接收在一个事务内校验全部检测柜和采集器在线可观测及必填映射完整;任一条件失败则整体回滚。暂停接收停止该测试的数据请求,继续接收恢复请求,停止测试进入不可恢复终态并释放业务占用。
- 检测柜通道允许运行中接入;同一次设备运行可依次服务多个测试,数据归属按测试级动作时间判断,不建立来源接收区间约束。
-- 停止测试或设备自然结束后进入内部“完成确认中”;只有所有来源补采完成且接收时段内没有未解释缺口、冲突或异常,才聚合为“检测完成”。
+- 停止测试或设备自然结束后直接进入“检测完成”;成功接收的数据追加保存,缺失、序号跳跃和采样间隔异常只作为可见事实。
- “检测完成”和“已终止”是不可恢复终态。异常恢复、数据缺口处置、终止和负责人转交都追加审计。
- 相同“测试 + 通道 + 异常类型”在未恢复期间聚合首次时间、最近时间和次数;恢复后关闭,再次发生创建新事件。
@@ -43,7 +42,7 @@
## 验证
-- 设备协议或调度改动至少覆盖正常多通道、拒绝连接、断线恢复、超时、畸形 XML、重复/乱序/缺失历史和重启补采中受影响的场景。
+- 设备协议或调度改动至少覆盖正常多通道、拒绝连接、断线、超时、畸形 XML 和实时数据幂等冲突等受影响场景。
- 运行设备模块测试:`mvn -pl ruoyi-device test`。
- 跨模块改动运行全量测试:`mvn test`。
- 验证可执行包:`mvn -pl ruoyi-admin -am package -DskipTests`。启动验证时使用可写的 `LOG_PATH`,完成后停止临时进程。
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/config/TestBackfillScheduler.java b/ruoyi-admin/src/main/java/com/ruoyi/config/TestBackfillScheduler.java
deleted file mode 100644
index 1968ab1..0000000
--- a/ruoyi-admin/src/main/java/com/ruoyi/config/TestBackfillScheduler.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.ruoyi.config;
-
-
-/** 以较低优先级执行历史补采;实时设备观测由既有调度器优先完成。 */
-public class TestBackfillScheduler
-{
- /** Ticket28 移除历史补采调度,保留空组件避免旧配置加载失败。 */
- public void reconcileAndBackfill() { }
-}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TTestLiveController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TTestLiveController.java
index 020a58a..872cc14 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TTestLiveController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TTestLiveController.java
@@ -24,7 +24,7 @@
@GetMapping("/{testId}/live-state")
public AjaxResult liveState(@PathVariable Long testId) { return success(liveService.current(testId)); }
- /** 查询测试完整性问题和可追溯的历史异常事实。 */
+ /** 推送实时快照、设备状态和可追溯的异常事实。 */
@PreAuthorize("@ss.hasPermi('system:test:query')")
@GetMapping(value = "/{testId}/live", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter live(@PathVariable Long testId) { return liveService.stream(testId); }
diff --git a/ruoyi-admin/src/main/resources/db/migration/V28__remove_reception_backfill_integrity_legacy.sql b/ruoyi-admin/src/main/resources/db/migration/V28__remove_reception_backfill_integrity_legacy.sql
index 7acca86..9788a2d 100644
--- a/ruoyi-admin/src/main/resources/db/migration/V28__remove_reception_backfill_integrity_legacy.sql
+++ b/ruoyi-admin/src/main/resources/db/migration/V28__remove_reception_backfill_integrity_legacy.sql
@@ -4,6 +4,8 @@
DROP TABLE t_test_integrity_issue;
DROP TABLE t_test_backfill_cursor;
+DROP TABLE t_data_gap;
+DROP TABLE t_history_sync_cursor;
DROP TABLE t_test_collector_exception_interval;
DROP TABLE t_test_reception_interval;
DROP TABLE t_collector_channel_lease;
diff --git a/ruoyi-admin/src/test/java/com/ruoyi/config/Ticket28MigrationContractTest.java b/ruoyi-admin/src/test/java/com/ruoyi/config/Ticket28MigrationContractTest.java
index 3c30450..515091c 100644
--- a/ruoyi-admin/src/test/java/com/ruoyi/config/Ticket28MigrationContractTest.java
+++ b/ruoyi-admin/src/test/java/com/ruoyi/config/Ticket28MigrationContractTest.java
@@ -16,6 +16,8 @@
assertTrue(sql.contains("DROP TABLE t_test_reception_interval"));
assertTrue(sql.contains("DROP TABLE t_collector_channel_lease"));
assertTrue(sql.contains("DROP TABLE t_channel_lease"));
+ assertTrue(sql.contains("DROP TABLE t_data_gap"));
+ assertTrue(sql.contains("DROP TABLE t_history_sync_cursor"));
assertTrue(sql.contains("DROP FOREIGN KEY fk_sample_reception_interval"));
assertTrue(sql.contains("DROP FOREIGN KEY fk_collector_sample_reception_interval"));
assertTrue(sql.contains("DROP COLUMN reception_interval_id"));
diff --git a/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/DeviceDiscoveryPersistenceServiceTest.java b/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/DeviceDiscoveryPersistenceServiceTest.java
index fc89c6a..aabb74f 100644
--- a/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/DeviceDiscoveryPersistenceServiceTest.java
+++ b/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/DeviceDiscoveryPersistenceServiceTest.java
@@ -29,7 +29,6 @@
DeviceAdapter adapter = Mockito.mock(DeviceAdapter.class);
ChannelIdentity identity = new ChannelIdentity("lab-bts", 22, 1, 1, 1);
when(testMapper.hasReceivingTestForAdapter("lab-bts")).thenReturn(0);
- when(testMapper.hasPausedOrEndedTestForAdapter("lab-bts")).thenReturn(1);
when(adapter.discoverChannels()).thenReturn(List.of(new DetectedChannel(identity, "127.0.0.1", true)));
when(registry.execute(eq("lab-bts"), any())).thenAnswer(invocation -> {
@SuppressWarnings("unchecked")
diff --git a/ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsDevelopmentSimulator.java b/ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsDevelopmentSimulator.java
index 5126a8f..cf28b98 100644
--- a/ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsDevelopmentSimulator.java
+++ b/ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsDevelopmentSimulator.java
@@ -70,7 +70,7 @@
{
this.stateStore = stateStore;
state = stateStore.loadOrInitialize(defaultState());
- // 仅清理 Ticket13 之前嵌在主状态中的旧演示历史;独立历史由存储实现保留并继续补采。
+ // 仅清理 Ticket13 之前嵌在主状态中的旧演示历史;独立历史由模拟器存储保留。
state = stateStore.resetHistoryForDemoStartup(state);
restoreBtsHistory();
validateRestoredState();
diff --git a/ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsXmlCodec.java b/ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsXmlCodec.java
index 11a74d7..27256d7 100644
--- a/ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsXmlCodec.java
+++ b/ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsXmlCodec.java
@@ -191,7 +191,7 @@
requiredAttribute(element, "steptype"), optionalLong(element, "testtime"), parseDeviceTime(rawTime), rawTime,
optionalDecimal(element, "volt"), optionalDecimal(element, "curr"), optionalDecimal(element, "cap"),
optionalDecimal(element, "eng"), dynamicMeasurements(element, HISTORY_ATTRIBUTES)));
- // 解析层保留重复和乱序事实;完整性检查按 seqid 另行判定并解释缺口。
+ // 解析层保留重复和乱序事实;业务层只展示并记录这些设备数据事实。
next = Math.max(next, sequence + 1);
}
return new HistoryPage(channel, btsTestId, requestedStart, next, samples);
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/TTestCollectorSource.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/TTestCollectorSource.java
deleted file mode 100644
index 766915d..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/TTestCollectorSource.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.ruoyi.system.domain;
-
-/** 接收中的测试采集器来源,供断线恢复协调器使用。 */
-public class TTestCollectorSource
-{
- private Long testId;
- private Long batteryRelationId;
- private String batteryNo;
- private Long collectorId;
- private String collectorCode;
- private String channelCode;
-
- public Long getTestId() { return testId; }
- public void setTestId(Long testId) { this.testId = testId; }
- public Long getBatteryRelationId() { return batteryRelationId; }
- public void setBatteryRelationId(Long batteryRelationId) { this.batteryRelationId = batteryRelationId; }
- public String getBatteryNo() { return batteryNo; }
- public void setBatteryNo(String batteryNo) { this.batteryNo = batteryNo; }
- public Long getCollectorId() { return collectorId; }
- public void setCollectorId(Long collectorId) { this.collectorId = collectorId; }
- public String getCollectorCode() { return collectorCode; }
- public void setCollectorCode(String collectorCode) { this.collectorCode = collectorCode; }
- public String getChannelCode() { return channelCode; }
- public void setChannelCode(String channelCode) { this.channelCode = channelCode; }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java
index 0bd548a..c1b9ff2 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java
@@ -51,7 +51,6 @@
List<TTestChannelBinding> selectTestChannelBindings(Long testId);
List<TTestCollectorChannel> selectTestCollectorChannels(Long testId);
List<TTestWarningThreshold> selectTestThresholds(Long testId);
- /** 按来源和起始边界顺序返回测试接收区间。 */
/** 查询当前正在接收的测试,供接收调度绑定测试事实。 */
List<Long> selectReceivingTestIds();
List<java.util.Map<String, Object>> selectPersistedRecords(@org.apache.ibatis.annotations.Param("testId") Long testId);
@@ -79,11 +78,7 @@
/** 锁定检测柜通道的最新可观测事实,供开始接收校验使用。 */
TDetectionChannel selectReceptionChannelForUpdate(Long channelId);
- /** 锁定当前检测柜通道租约;返回空表示可接入。 */
- /** 为每个绑定来源追加一个开放接收区间;区间关闭后仅保留历史事实。 */
- /** 在停止动作事务内关闭该测试全部开放区间,返回实际关闭数量。 */
int hasReceivingTestForAdapter(@Param("adapterCode") String adapterCode);
- int hasPausedOrEndedTestForAdapter(@Param("adapterCode") String adapterCode);
List<TDetectionChannel> selectReceivingChannelsForAdapter(@Param("adapterCode") String adapterCode);
boolean collectorOnline(Long collectorId);
int updateReceptionStarted(@Param("testId") Long testId, @Param("startedAtUtc") Date startedAtUtc,
@@ -95,18 +90,11 @@
int updateReceptionStopped(@Param("testId") Long testId, @Param("updateBy") String updateBy,
@Param("endedAtUtc") Date endedAtUtc);
- /** 查询仍在接收中的采集器来源。 */
- /** 查询来源当前开放的断线区间。 */
String selectBtsSampleContentHash(@Param("channelId") Long channelId, @Param("btsTestId") String btsTestId,
@Param("sequenceId") Long sequenceId);
- /** 查询需要自然结束或继续补采的测试。 */
- /** 按稳定来源身份锁定补采游标,避免应用重启重复推进。 */
- /** 按测试事实查询通道序号,避免补采重复写入已即时接收的采样。 */
- String selectTestSampleContentHash(@Param("testId") Long testId, @Param("channelId") Long channelId,
- @Param("sequenceId") Long sequenceId);
int insertBtsSample(@Param("testId") Long testId, @Param("bindingId") Long bindingId,
- @Param("channelId") Long channelId, @Param("intervalId") Long intervalId,
+ @Param("channelId") Long channelId,
@Param("btsTestId") String btsTestId, @Param("sequenceId") Long sequenceId,
@Param("deviceTimeUtc") Date deviceTimeUtc, @Param("deviceTimeRaw") String deviceTimeRaw,
@Param("receivedAtUtc") Date receivedAtUtc, @Param("cycleNo") Integer cycleNo,
@@ -117,20 +105,13 @@
int insertBtsMeasurement(@Param("sampleId") Long sampleId, @Param("metricCode") String metricCode,
@Param("metricValue") java.math.BigDecimal metricValue, @Param("unit") String unit,
@Param("sourceType") String sourceType);
- Long selectBtsSampleId(@Param("channelId") Long channelId, @Param("btsTestId") String btsTestId,
- @Param("sequenceId") Long sequenceId);
int insertCollectorSample(@Param("testId") Long testId, @Param("bindingId") Long bindingId,
- @Param("intervalId") Long intervalId, @Param("collectorId") Long collectorId,
+ @Param("collectorId") Long collectorId,
@Param("channelCode") String channelCode,
@Param("sequenceId") Long sequenceId, @Param("deviceTimeUtc") Date deviceTimeUtc,
@Param("deviceTimeRaw") String deviceTimeRaw, @Param("receivedAtUtc") Date receivedAtUtc,
@Param("metricCode") String metricCode, @Param("metricValue") java.math.BigDecimal metricValue,
@Param("unit") String unit, @Param("contentSha256") byte[] contentSha256);
- Long selectCollectorSampleId(@Param("collectorId") Long collectorId, @Param("channelCode") String channelCode,
- @Param("sequenceId") Long sequenceId, @Param("metricCode") String metricCode);
- String selectCollectorSampleContentHash(@Param("collectorId") Long collectorId,
- @Param("channelCode") String channelCode, @Param("sequenceId") Long sequenceId,
- @Param("metricCode") String metricCode);
int insertDataRevisionAction(TTestDataRevisionAction action);
List<TTestDataRevisionAction> selectDataRevisionActions(TTestDataRevisionAction query);
TTestDataRevisionAction selectDataRevisionActionById(Long actionId);
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestServiceImpl.java
index f0135c4..13f5179 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestServiceImpl.java
@@ -221,7 +221,7 @@
Date actionAt = new Date();
if (testMapper.updateReceptionPaused(testId, updateBy, actionAt) != 1)
throw new ServiceException("测试状态已变更,请刷新后重试");
- // 暂停边界不属于本次测试的确认接收区间,继续时由新的区间重新开始计时。
+ // 暂停期间停止请求数据;继续接收后仅追加新的成功接收事实。
testMapper.insertTestAudit(testId, "RECEPTION_PAUSED", operatorId, updateBy, null,
JSON.toJSONString(Map.of("receptionStatus", "PAUSED", "polling", "STOPPED")));
return 1;
@@ -237,7 +237,7 @@
if (current == null) throw new ServiceException("测试不存在");
if (!"PAUSED".equals(current.getReceptionStatus()))
throw new ServiceException("当前测试不是暂停接收状态");
- // 加锁查询只返回测试主表,继续接收需要完整绑定配置来重建各来源接收区间。
+ // 加锁查询只返回测试主表,继续接收前重新加载绑定配置以校验来源仍可用。
loadConfiguration(current);
Date actionAt = new Date();
if (testMapper.updateReceptionResumed(testId, updateBy, actionAt) != 1)
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TestDataReceptionServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TestDataReceptionServiceImpl.java
index 381adfb..874f0ce 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TestDataReceptionServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TestDataReceptionServiceImpl.java
@@ -79,7 +79,7 @@
"实时接收内容冲突 testid=" + btsTestId + ", seqid=" + record.sequenceId());
return;
}
- int inserted = mapper.insertBtsSample(test.getTestId(), binding.getBindingId(), binding.getChannelId(), null,
+ int inserted = mapper.insertBtsSample(test.getTestId(), binding.getBindingId(), binding.getChannelId(),
btsTestId, record.sequenceId(), Date.from(record.deviceTime()),
record.deviceTime().toString(), new Date(), record.cycleNo(), record.stepNo(), record.stepType(),
record.stepName(), null,
diff --git a/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml
index d3b21e5..4dd1e22 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml
@@ -96,7 +96,6 @@
<result property="maxValue" column="max_value" />
<result property="unit" column="unit" />
<result property="unitMetadata" column="unit_metadata" />
- <result property="integrityConclusion" column="integrity_conclusion" />
<result property="severity" column="severity" />
<result property="delFlag" column="del_flag" />
</resultMap>
@@ -496,10 +495,6 @@
for update
</select>
- <update id="updateTestCompleted">
- update t_test set test_status = 'COMPLETED', update_time = #{updatedAtUtc}
- where test_id = #{testId} and reception_status = 'ENDED' and test_status = 'COMPLETION_PENDING'
- </update>
<select id="selectBtsSampleContentHash" resultType="string">
select hex(content_sha256) from t_test_sample
where channel_id = #{channelId} and bts_test_id = #{btsTestId} and seq_id = #{sequenceId}
@@ -519,10 +514,6 @@
(sample_id, metric_code, metric_value, unit, source_type)
values (#{sampleId}, #{metricCode}, #{metricValue}, #{unit}, #{sourceType})
</insert>
- <select id="selectBtsSampleId" resultType="long">
- select sample_id from t_test_sample
- where channel_id = #{channelId} and bts_test_id = #{btsTestId} and seq_id = #{sequenceId}
- </select>
<insert id="insertCollectorSample">
insert ignore into t_test_collector_sample
(test_id, binding_id, collector_id, collector_channel_code, sequence_id, device_time_utc,
@@ -530,16 +521,6 @@
values (#{testId}, #{bindingId}, #{collectorId}, #{channelCode}, #{sequenceId}, #{deviceTimeUtc},
#{deviceTimeRaw}, #{receivedAtUtc}, #{metricCode}, #{metricValue}, #{unit}, #{contentSha256})
</insert>
- <select id="selectCollectorSampleId" resultType="long">
- select sample_id from t_test_collector_sample
- where collector_id = #{collectorId} and collector_channel_code = #{channelCode}
- and sequence_id = #{sequenceId} and metric_code = #{metricCode}
- </select>
- <select id="selectCollectorSampleContentHash" resultType="string">
- select hex(content_sha256) from t_test_collector_sample
- where collector_id = #{collectorId} and collector_channel_code = #{channelCode}
- and sequence_id = #{sequenceId} and metric_code = #{metricCode}
- </select>
<insert id="insertSampleConflict">
insert into t_test_exception
(test_id, channel_id, exception_type, exception_status, severity,
diff --git a/scripts/clear-development-data.sql b/scripts/clear-development-data.sql
index b1dd45d..c19bd8e 100644
--- a/scripts/clear-development-data.sql
+++ b/scripts/clear-development-data.sql
@@ -6,13 +6,6 @@
TRUNCATE TABLE t_test_sample_measurement;
TRUNCATE TABLE t_test_sample;
TRUNCATE TABLE t_test_collector_sample;
-TRUNCATE TABLE t_test_backfill_cursor;
-TRUNCATE TABLE t_history_sync_cursor;
-TRUNCATE TABLE t_data_gap;
-TRUNCATE TABLE t_test_integrity_issue;
-TRUNCATE TABLE t_test_reception_interval;
-TRUNCATE TABLE t_channel_lease;
-TRUNCATE TABLE t_collector_channel_lease;
TRUNCATE TABLE t_channel_snapshot;
TRUNCATE TABLE t_device_run_event;
TRUNCATE TABLE t_test_exception;
--
Gitblit v1.7.1