| | |
| | | /** 供业务持久化使用的厂商无关测试数据观测扩展。 */ |
| | | public interface TestDataObservationAdapter extends DeviceObservationAdapter |
| | | { |
| | | /** 返回指定检测柜通道最近一次实时观测;没有成功观测时返回空值。 */ |
| | | CabinetRealtime latestCabinet(ChannelIdentity channel); |
| | | |
| | | /** 返回采集器独立实时快照;不得通过历史下载补采。 */ |
| | | CollectorRealtime latestCollector(long collectorId); |
| | | |
| | | /** 返回设备直接提供的工步统计,不从实时采样推导。 */ |
| | | List<StepRecord> stepRecords(ChannelIdentity channel); |
| | | |
| | | /** 返回设备直接提供的循环统计,不补齐设备未返回的记录。 */ |
| | | List<CycleRecord> cycleRecords(ChannelIdentity channel); |
| | | |
| | | /** 返回适配器定义的实时持久化槽位间隔。 */ |
| | | long persistenceIntervalMillis(ChannelIdentity channel); |
| | | |
| | | record CabinetRealtime(long sequenceId, Instant deviceTime, double currentA, double voltageV, |
| | |
| | | -- Ticket08:补齐三类测试事实的绑定、接收时间、来源编号和幂等键;原始事实只追加不覆盖。 |
| | | ALTER TABLE t_test_realtime_record |
| | | ADD COLUMN source_identity VARCHAR(256) NULL AFTER adapter_code, |
| | | ADD COLUMN source_record_id VARCHAR(128) NULL AFTER source_identity; |
| | |
| | | MODIFY COLUMN dedupe_key VARCHAR(512) NOT NULL, |
| | | MODIFY COLUMN server_received_at_utc DATETIME(3) NOT NULL, |
| | | DROP INDEX uk_step_identity, |
| | | -- 前缀索引控制 InnoDB 索引长度,同时保留来源身份和幂等键的稳定区分。 |
| | | ADD UNIQUE KEY uk_step_dedupe (test_battery_id, source_identity(128), dedupe_key(128)), |
| | | ADD KEY idx_step_binding_time (binding_id, server_received_at_utc); |
| | | |
| | |
| | | |
| | | private void saveRealtime(TTest test, TTestBattery battery) |
| | | { |
| | | // 柜端和采集器端分别判断成功;同一槽位只写一行,失败来源的身份、时间和指标保持为空。 |
| | | if (adapter == null) return; |
| | | TTestChannelBinding binding = battery.getBinding(); if (binding == null || binding.getDevid() == null || binding.getChlid() == null) return; |
| | | Instant now = clock.instant(); long interval = persistenceInterval(binding); String key = test.getTestId() + ":" + battery.getTestBatteryId(); |
| | |
| | | |
| | | private void saveDeviceAggregates(TTest test, TTestBattery battery) |
| | | { |
| | | // 工步、循环只接受设备直接返回的统计记录,并以来源编号或明确的时间组合执行幂等。 |
| | | if (adapter == null) return; TTestChannelBinding binding = battery.getBinding(); if (binding == null || binding.getDevid() == null || binding.getChlid() == null) return; |
| | | ChannelIdentity channel = new ChannelIdentity(binding.getAdapterCode(), binding.getDevtype(), binding.getDevid(), binding.getSubdevid(), binding.getChlid()); |
| | | List<StepRecord> steps; List<CycleRecord> cycles; try { steps = adapter.stepRecords(channel); cycles = adapter.cycleRecords(channel); } catch (RuntimeException ex) { return; } |