Bladeren bron

fix(cockpit): 补齐事件与边界 freshness

Kazerin 3 weken geleden
bovenliggende
commit
8086c0d803

+ 1 - 0
docs/cockpit/README.md

@@ -203,6 +203,7 @@ mvn -pl zksy-admin -am test -Dtest='Cockpit*Test'
 - 第 7 轮补充 Redis GET/SET 运行时异常测试:适配器将缓存连接故障包装为 `CockpitReadException`,控制器契约映射为 `500 SERVER_ERROR`,不误报为 `SNAPSHOT_EXPIRED`;定向与全量回归均通过。
 - 第 8 轮本机受控性能烟测:同一真实 `snapshotAt` 连续认证请求 30 次,30/30 成功,平均 24.10ms、P95 30.60ms、最大 34.35ms;本次 live 数据样例 `total=7`。该结果仅代表本机进程和当前数据量,不替代生产规模压测。
 - 第 9 轮逐端点扫描:16 个主要 endpoint 全部 HTTP/app code 200;扫描到的全部 ISO 时间戳均为 `+08:00`。其中 11 个 endpoint 显式提供 freshness;`events/current`、`events/history-analysis`、`events/handling-efficiency`、`events/multidimensional-analysis` 和 `device-boundary` 当前没有统一 freshness 字段,仍是未完成契约项。
+- 第 10 轮为 `events/current`、`events/history-analysis`、`events/handling-efficiency`、`events/multidimensional-analysis` 和 `device-boundary` 响应 DTO 补充兼容 `freshness` getter:按已有事件/边界数据返回 `CURRENT` 或 `EMPTY`,不改变既有构造器;定向与全量回归均通过。
 - **验收边界**:上述 200/readOnly 证明当前本机实例的认证与响应契约,不等于 #63 全部切片的代表性真实数据、空/脏数据及故障场景均已验收。静态装配盘点显示 23 个 `Empty*Adapter` 均有对应的 `@Primary Business*Adapter`(另有 1 个共享事件事实适配器);`Empty*Adapter` 作为 fallback 保留,不能仅凭类仍存在判断运行时未接线。目标部署实例仍需验收,issue 保持开启。
 - WebSocket `/ws/deviceStatus` 真实浏览器验收通过:发送 `cockpitSubscribe(scope=all)` 后收到 `cockpitSubscribed`,响应带 `serverUpdatedAt`;所有抽查时间戳为 `+08:00`。
 - 目标部署地址 `192.168.110.30:8301` TCP 不可达,因此没有把它当作本轮 HTTP 证据;生产部署实例、性能压测、银河麒麟与 Docker 实机验证仍未执行。

+ 6 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/device/CockpitDeviceBoundaryResponse.java

@@ -1,6 +1,7 @@
 package com.zksy.cockpit.device;
 
 import java.util.List;
+import com.zksy.cockpit.foundation.CockpitFreshnessStatus;
 
 public class CockpitDeviceBoundaryResponse {
     private final String requestId;
@@ -30,4 +31,9 @@ public class CockpitDeviceBoundaryResponse {
     public List<CockpitFacilityBoundary> getFacilities() { return facilities; }
     public List<CockpitDeviceBoundary> getDevices() { return devices; }
     public CockpitDeviceBoundaryStatistics getStatistics() { return statistics; }
+    public CockpitFreshnessStatus getFreshness() {
+        boolean hasFacilities = facilities != null && !facilities.isEmpty();
+        boolean hasDevices = devices != null && !devices.isEmpty();
+        return hasFacilities || hasDevices ? CockpitFreshnessStatus.CURRENT : CockpitFreshnessStatus.EMPTY;
+    }
 }

+ 10 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/event/CockpitCurrentEventsResponse.java

@@ -2,6 +2,7 @@ package com.zksy.cockpit.event;
 
 import com.zksy.cockpit.detail.CockpitSectionResult;
 import com.zksy.cockpit.foundation.CockpitCoordinateValidation;
+import com.zksy.cockpit.foundation.CockpitFreshnessStatus;
 
 import java.math.BigDecimal;
 import java.util.List;
@@ -54,6 +55,15 @@ public class CockpitCurrentEventsResponse {
     public Filters getFilters() { return filters; }
     public Pagination getPagination() { return pagination; }
     public MapFilter getMapFilter() { return mapFilter; }
+    public CockpitFreshnessStatus getFreshness() {
+        if (sections == null || sections.getEvents() == null
+                || sections.getEvents().getState() == com.zksy.cockpit.detail.CockpitSectionState.FAILED) {
+            return CockpitFreshnessStatus.FAILED;
+        }
+        return sections.getEvents().getData() == null || sections.getEvents().getData().isEmpty()
+                ? CockpitFreshnessStatus.EMPTY : CockpitFreshnessStatus.CURRENT;
+    }
+
     public Sections getSections() { return sections; }
 
     public static class Filters {

+ 5 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/event/CockpitHandlingEfficiencyResponse.java

@@ -1,6 +1,7 @@
 package com.zksy.cockpit.event;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.zksy.cockpit.foundation.CockpitFreshnessStatus;
 
 import java.math.BigDecimal;
 import java.util.List;
@@ -70,6 +71,10 @@ public class CockpitHandlingEfficiencyResponse {
     public List<WorkOrderStateCount> getWorkOrderStateCounts() { return workOrderStateCounts; }
     public List<DurationPoint> getDurationTrend() { return durationTrend; }
     public List<EventItem> getEvents() { return events; }
+    public CockpitFreshnessStatus getFreshness() {
+        return events == null || events.isEmpty()
+                ? CockpitFreshnessStatus.EMPTY : CockpitFreshnessStatus.CURRENT;
+    }
 
     public static class Range {
         private final String type;

+ 5 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/event/CockpitHistoryAnalysisResponse.java

@@ -1,6 +1,7 @@
 package com.zksy.cockpit.event;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.zksy.cockpit.foundation.CockpitFreshnessStatus;
 
 import java.math.BigDecimal;
 import java.util.List;
@@ -54,6 +55,10 @@ public class CockpitHistoryAnalysisResponse {
     public Filters getFilters() { return filters; }
     public Summary getSummary() { return summary; }
     public List<Row> getRows() { return rows; }
+    public CockpitFreshnessStatus getFreshness() {
+        return rows == null || rows.isEmpty()
+                ? CockpitFreshnessStatus.EMPTY : CockpitFreshnessStatus.CURRENT;
+    }
 
     public static class Range {
         private final String type;

+ 4 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/event/CockpitMultidimensionalAnalysisResponse.java

@@ -1,6 +1,7 @@
 package com.zksy.cockpit.event;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.zksy.cockpit.foundation.CockpitFreshnessStatus;
 
 import java.math.BigDecimal;
 import java.util.List;
@@ -58,6 +59,9 @@ public class CockpitMultidimensionalAnalysisResponse {
     public int getTotalCount() { return totalCount; }
     public MapFilter getMapFilter() { return mapFilter; }
     public List<Dimension> getDimensions() { return dimensions; }
+    public CockpitFreshnessStatus getFreshness() {
+        return totalCount == 0 ? CockpitFreshnessStatus.EMPTY : CockpitFreshnessStatus.CURRENT;
+    }
 
     public static class Range {
         private final String type;