Эх сурвалжийг харах

Merge remote-tracking branch 'origin/master'

zengy 3 долоо хоног өмнө
parent
commit
5250b21457

+ 2 - 1
docs/cockpit/README.md

@@ -202,7 +202,8 @@ mvn -pl zksy-admin -am test -Dtest='Cockpit*Test'
 - 第 4 轮真实 HTTP 复核(重启加载 `f33b9bf`):首屏无 token 返回 200 并签发 `snapshotAt=+08:00`、`total=15`;使用该 token 请求第 2 页返回 200、同 `snapshotAt`、同 `total`;第 2 页缺 token 和使用旧未签发 token 均返回 400(契约类别由 MockMvc 固化为 `SNAPSHOT_EXPIRED`)。
 - 第 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 字段,仍是未完成契约项。
+- 第 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 轮重启后的本机真实登录态复验:上述 5 个端点均返回 HTTP/app code 200、`readOnly=true` 和 `freshness=CURRENT`。该结果仅确认当前非空样本的字段与状态;尚未证明数据的实际时效或空数据、故障场景下的状态准确性。
 - **验收边界**:上述 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 实机验证仍未执行。

+ 2 - 0
pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/cockpit/CockpitCurrentEventsControllerTest.java

@@ -64,6 +64,7 @@ class CockpitCurrentEventsControllerTest {
                 .andExpect(jsonPath("$.data.requestId").value("current-warnings-001"))
                 .andExpect(jsonPath("$.data.apiVersion").value("v1"))
                 .andExpect(jsonPath("$.data.readOnly").value(true))
+                .andExpect(jsonPath("$.data.freshness").value("CURRENT"))
                 .andExpect(jsonPath("$.data.displayName").value("当前预警"))
                 .andExpect(jsonPath("$.data.timezone").value("Asia/Shanghai"))
                 .andExpect(jsonPath("$.data.mode").value("WARNING"))
@@ -197,6 +198,7 @@ class CockpitCurrentEventsControllerTest {
                 .andExpect(jsonPath("$.data.sections.events.reason").value("NO_EVENTS"))
                 .andExpect(jsonPath("$.data.sections.events.data").value(nullValue()))
                 .andExpect(jsonPath("$.data.sections.workOrders.state").value("EMPTY"))
+                .andExpect(jsonPath("$.data.freshness").value("EMPTY"))
                 .andExpect(jsonPath("$.data.mapFilter.deviceCodes", hasSize(0)));
     }
 

+ 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;