52-untitled.md 16 KB

后端执行票 —— 单设备业务优先级裁定落地(全部报警均有未结束工单时工单处置最高)

Category: backend-execution

来源

前端执行票 45 实施前裁定(维护者 2026-10-16):

  • 监测点聚合:维持报警优先级最高(后端现行语义不动)。
  • 单设备:只要该设备的所有报警都有对应的工单(即报警均已被工单承接、处置在进行),单设备自身状态应判工单处置最高——高于报警/预警。
  • 判定权归后端;前端只渲染(CONTEXT.md / ADR 0002 不变)。

现状证据(前端票 45 侦察)

  • 权威解析器 CockpitMonitoringPointStatusResolver.deviceStatus() 现行顺序: alarm → warning → workOrderInProgress → online?NORMAL:OFFLINE,即报警恒压工单。 实测设备 21119740(alarm=true, warning=true, workOrderInProgress=true)→ 后端判 ALARM; 按裁定应为工单处置(其报警已有工单承接时)。
  • CockpitMonitoringPointStatus 枚举优先级 ALARM(1)/WARNING(2)/WORK_ORDER(3)/NORMAL(4)/OFFLINE(5)/EMPTY(6)。
  • map-snapshot 不携带工单布尔——前端无法也不得自行判定。

范围

  1. 明确「所有报警均有对应工单」的判定口径(报警-工单回联读模型已有 alarm_data.work_order_id 关联,票 12 已核实关联键)。
  2. 调整单设备状态解析:设备存在报警、且每条报警均有未结束/已关联工单时 → WORK_ORDER(工单处置);否则维持现行序。 注意只影响单设备状态(设备卡片 deviceStatus、快照未关联设备 deviceStatus、统计计数),监测点聚合 resolve() 语义由维护者另行确认是否跟随(聚合用 min(priority),若单设备可判 WORK_ORDER(3) 而报警设备判 WORK_ORDER,聚合优先级序是否需把 WORK_ORDER 提到 ALARM 之前,须裁定并同步枚举 priority 与前端词表)。
  3. 契约测试覆盖:报警无工单 → ALARM;全部报警有工单 → WORK_ORDER;混合 → 按裁定;无报警维持现状。
  4. 落地后通知前端票 45 消费侧复核(前端 DEVICE_STATUS_VISUALS.priority 与 POINT_STATUS_VISUALS.priority 需同步新序——前端票 45 已按双轴实现,priority 同步是唯一耦合点)。

非目标

  • 不改前端代码(前端词表同步由票 45 收口时复核)。
  • 不动监测点聚合 resolve() 除非第 2 条裁明确认需要。

进度

已实施、验证、推送完成(2026-10-17)→ 关闭。

提交 3772220e + 编译解阻 5d4d03c6,已推 origin/master(远端核实 3772220e)。 Cockpit*Test,BusinessCockpit*Test 512/512;变异闸 7/7 打红并字节还原;前端 t09 38/38(零耦合,裁定 4 成立)。

裁定全部落地:只取未处理报警(alarm_status=0);承接=work_order_id 非空且工单 order_status ∈ {0..4,6}; 空集/读失败 → 维持 ALARM;resolve() 与枚举 priority 不动;已推送。

两处如实留档:① 票面「21119740 应为工单处置」被真实数据证伪(该设备 2 条未处理报警均无工单承接, 按裁定应为 ALARM);② 新规则在当前数据上不改变任何读数(正确行为,非未生效)。 zksy-system 全量 2 失败/1 错误为既有(stash 对照逐条相同),与本票零交集。

下一步:无(本票交付物已闭环)。前端消费侧无需跟随改动。

Status: resolved Type: task Blocked by: Labels: wayfinder:task, backend-execution

Comments

local — 2026-10-16T18:13:25.050Z

阶段闸门诊断完成(2026-10-17):当前工作树是前端 City-Lifeline-Cockpit(origin=192.168.110.30/ChenJZ/City-Lifeline-Cockpit),没有后端 Java/Maven/Gradle 源码或 CockpitMonitoringPointStatusResolver;后端仓库/负责人/权限未提供。只读真实接口复核:map-snapshot 仍返回设备 21119740 的 ALARM,设备工单接口中存在多条未结束工单但也有未关联当前报警的工单;因此票面“全部报警均有未结束/已关联工单”的设备级判据不能从现有设备汇总直接推断,需要后端按每条当前报警关联键(alarm_data.work_order_id)且工单状态 0–4/6 视为未结束,状态 5/7 视为结束,空/缺关联即不满足。未改前端或模拟后端,避免越权猜测。

local — 2026-10-16T18:32:36.319Z

【诊断记录 2026-10-17 —— 后端仓库已定位,票面前提与真实数据不符,判定口径待裁定】

local — 2026-10-16T18:46:42.632Z

【维护者裁定 2026-10-17(5 项,全部采纳推荐项)—— 据此实施】

  1. 报警范围:只取未处理报警(alarm_data.alarm_status = 0)。已处理的历史流水不参与。
  2. 承接判据:alarm_data.work_order_id 非空 且 该工单未结束(work_order.order_status ∈ {0,1,2,3,4,6},0-based;5 已结案 / 7 已取消为终态)。
  3. 空集与缺数据:设备 alarm 标志为真但取不到任何未处理报警行(或根本没有 alarm_data 行)→ 维持现行序 → ALARM(「查不到」不等于「已承接」)。
  4. 聚合与优先级:不跟随。resolve() 与枚举 priority 不改,前端 POINT_STATUS_VISUALS.priority 零改动、无耦合;仅单设备 deviceStatus() 按新规则判定。
  5. 交付边界:提交并推送 origin/master。

本条同时记录一处契约边界(非目标,如实留档):monitoring/situation 的设备 metricStatus(BusinessCockpitMonitoringSituationAdapter.metricStatus())词表为 NORMAL/WARNING/ALARM/EXPIRED/OFFLINE/UNKNOWN,没有 WORK_ORDER 桶,因此本次不改它——改它需要动 situation 响应契约,超出本票范围。

local — 2026-10-16T19:24:28.181Z

【实施完成 2026-10-17 —— 已提交并推送 origin/master】

提交:3772220e(本票) + 5d4d03c6(编译解阻)→ 已推 origin/master(git ls-remote 核实远端 master = 3772220e,本地/远端 0 ahead/0 behind)。推送前远端已有 2 个新提交,已 git fetch + rebase 后复跑测试再推(未强推)。

交付

判定单源仍是 CockpitMonitoringPointStatusResolver.deviceStatus(): 报警且 isAlarmsCoveredByOpenWorkOrders() → WORK_ORDER,否则维持现行序。

事实由 BusinessCockpitDeviceFactResolver 新增计算(新增 AlarmDataService 依赖): 取 alarm_data.alarm_status=0 的行,每一条都要有 work_order_id 且对应工单 order_status ∈ {0..4,6};无未处理行 / 任一行不满足 / 读失败 → false(保守降级为 ALARM)。

三处透传接缝(丢任一处结论都会被抹掉,变异 M6/M7 专门钉住): CockpitMonitoringPointDeviceSnapshot、分布快照 SourceSmartDevice + 分布适配器、 CockpitMonitoringDistributionService.effectiveDevice() 重建、CockpitMonitoringPointDetailService 归一化。

验证

  • Cockpit*Test,BusinessCockpit*Test 512/512(基线 510 + 本票新增 2)。
  • 变异闸 t52-mutations.mjs 7/7 打红并按字节还原;覆盖:判定分支删除、判据放宽为「至少一条」、已结案/已取消算作承接、空集视为已承接、去掉 alarm_status 过滤、分布适配器不透传、effectiveDevice 重建丢事实。
  • 真实载荷取证 real-data-consequence.md。
  • 前端 t09 闸门 38/38(priority 与词表零改动,确认裁定 4「不跟随」成立)。

顺带修复(既有阻塞,非本票引入)

zksy-system 在 HEAD 上根本编译不过:SseEmitterManager(5bc0c6e4 引入)用 SseEmitter, 而 spring-webmvc 只由 springfox-spring-webmvc 以 provided 传递(provided 不参与编译期), 模块编译期缺类。已按 same-scope 显式声明 provided 补齐编译期(5d4d03c6);运行期无影响 (boot 包 BOOT-INF/lib 本就含该 jar)。未改任何运行语义。

既有失败(如实登记,与本票零交集)

zksy-system 全量另有 2 失败 / 1 错误:AlarmLifecycleServiceTest.insertWritesLogBeforeCommittingWithoutTrigger、 WorkOrderServiceImplTest.cancelDoesNotWriteSuccessLogWhenStatusChangesConcurrently / cancelAllowsOnlyOrdersAwaitingDispatchOrAcceptance。 已把本票源码整体 git stash 后复跑,同样 2 失败/1 错误、逐条相同 → 确认为 HEAD 级既有失败。

两点如实留档

  1. 票面举例被证伪:票面写「实测 21119740 按裁定应为工单处置」。实测该设备 2 条未处理报警 都没有工单承接,按裁定就应当是 ALARM。票面把设备级 workOrderInProgress(该设备存在任意 未结束工单)误当成了「未处理报警已被逐条承接」——两者不是同一事实。
  2. 新规则在当前真实数据上不改变任何设备读数(今天不存在「未处理且已承接」的报警行)。 这是正确行为而非未生效;待业务侧为未处理报警建单后,该设备才会由 ALARM 变 WORK_ORDER。

消费侧影响

前端零改动(裁定 4):POINT_STATUS_VISUALS/DEVICE_STATUS_VISUALS 的 priority (ALARM 1 / WARNING 2 / WORK_ORDER 3)与后端枚举一致,本次未动枚举。 monitoring/situation 的 metricStatus 词表无 WORK_ORDER 桶,仍按现状(已在裁定评论留档为非目标)。

1. 交付环境(已具备)

  • 后端仓库:E:\pipe-ner-server,远端 http://192.168.110.30:3000/shaoy/pipe-ner-server.git,master = origin/master = 91444f51(feat(alarm): 扩展报警指标并重构遥测报警评估逻辑),工作树干净。
  • 只读数据库可达:KingbaseES 192.168.110.30:54321 / pipi_ner(schema app_user),已用 psql 直连核对(非只看接口自证)。
  • 模块:后端代码在 pipe-network-service/zksy-system(域)与 zksy-admin(控制器+测试)。

2. 权威链(现状)

CockpitMonitoringPointStatusResolver(zksy-system/src/main/java/com/zksy/cockpit/point/):

  • deviceStatus():alarm → warning → workOrderInProgress → online ? NORMAL : OFFLINE(报警恒压工单)。
  • 枚举 CockpitMonitoringPointStatus:ALARM(1)/WARNING(2)/WORK_ORDER(3)/NORMAL(4)/OFFLINE(5)/EMPTY(6)。
  • 调用点(改 deviceStatus 即全覆盖):resolve() 点位聚合(min priority)、cards() 设备卡 deviceStatus、statistics() 设备统计计数、orderedDevices() 排序、getPublishedDeviceStatus()(快照/未关联设备 deviceStatus)。

事实来源 BusinessCockpitDeviceFactResolver.resolve():

  • alarm = equipment_status.alarm_status == 1(设备级报警标志)。
  • warning = early_warning.status ∈ {PENDING, PROCESSING, HANDLING, RELEASED}。
  • workOrderInProgress = 该设备任意一张 work_order.order_status ∈ {0,1,2,3,4,6}(0-based;5 已结案、7 已取消为终态)——不与报警逐条回联。

3. 真实数据(推翻票面前提)

alarm_data 是报警历史流水(同一设备的重复报警会一行一条):

事实 实测
alarm_data 全表行数 / 涉及设备 90 行 / 仅 21119740 一台
未处理(alarm_status=0) 2 行(BJ202610161600430761、BJ202610101851389458)
带 work_order_id 的行 2 行,且这 2 行 alarm_status 都是 1(已处理)
「未处理 且 已关联工单」的行 0 行
已关联工单的两条报警 89b53f56…→WO291(order_status=0 待派单,未结束);e68a942d…→WO287(order_status=5 已结案)
设备 21119740 equipment_status.alarm_status=1、online_status=1;7 张工单,3 张未结束(291=0、286=1、285=3)

因此票面「实测设备 21119740(alarm=true, warning=true, workOrderInProgress=true)→ 按裁定应为工单处置(其报警已有工单承接时)」无法成立:该设备当前的 2 条未处理报警都没有工单承接;有工单的那 2 条报警都已经是「已处理」历史记录。

4. 为什么必须先裁定

范围第 1 条要求「明确『所有报警均有对应工单』的判定口径」,范围第 2 条又要求「监测点聚合语义由维护者另行确认」。上述数据事实使这两条各自都有多种自洽读法、且结果可观测不同(同一台设备在四种口径下两种判 ALARM、两种判 WORK_ORDER),按纪律不猜。 另:CockpitMonitoringPointStatus 的 priority 同时驱动点位聚合(min)与前端图例排序(前端 POINT_STATUS_VISUALS.priority 与 t09 A3 闸门按此锁定),是否调整属维护者裁定范围。

5. 尚未动工

本轮只做诊断与事实核对,未改任何后端代码,未提交、未推送。裁定后按单源(deviceStatus())实施并补契约测试。

Answer

已实施、验证并推送关闭(2026-10-17)。

裁定口径(维护者 2026-10-17,5 项)

单设备存在报警(equipment_status.alarm_status=1)、且该设备全部未处理报警 (alarm_data.alarm_status=0)都满足 work_order_id 非空 且 对应工单 work_order.order_status ∈ {0,1,2,3,4,6}(未结束;5 已结案、7 已取消为终态) → 判 WORK_ORDER;否则维持现行序。无未处理报警行 / 任一行不满足 / 读失败 → 保守判 ALARM。 resolve() 聚合与枚举 priority 不动(前端零耦合)。

交付

  • 判定单源:CockpitMonitoringPointStatusResolver.deviceStatus()。
  • 事实计算:BusinessCockpitDeviceFactResolver.alarmsCoveredByOpenWorkOrders()(新增 AlarmDataService 依赖)。
  • 三处事实透传接缝(丢任一处结论会被抹掉):CockpitMonitoringPointDeviceSnapshot、 分布快照 SourceSmartDevice + BusinessCockpitMonitoringDistributionAdapter、 CockpitMonitoringDistributionService.effectiveDevice() 重建、CockpitMonitoringPointDetailService 归一化。
  • 提交 3772220e(本票)+ 5d4d03c6(既有编译阻塞修复)→ 已推 origin/master(git ls-remote 核实远端 = 3772220e)。

验证

  • Cockpit*Test,BusinessCockpit*Test 512/512(基线 510 + 新增 2)。
  • 变异闸 t52-mutations.mjs 7/7 打红并按字节还原; 覆盖:判定分支删除、判据放宽为「至少一条」、已结案/已取消算作承接、空集视为已承接、 去掉 alarm_status 过滤、分布适配器不透传、effectiveDevice 重建丢事实。
  • 真实载荷取证 real-data-consequence.md。
  • 前端 t09 闸门 38/38(确认裁定 4「不跟随」成立)。

两点如实留档

  1. 票面举例被证伪:票面写「实测 21119740 按裁定应为工单处置」。实测该设备 2 条未处理报警 都没有工单承接,按裁定就应当是 ALARM。票面把设备级 workOrderInProgress (该设备存在任意未结束工单)误当成了「未处理报警已被逐条承接」——两者不是同一事实。
  2. 新规则在当前真实数据上不改变任何设备读数(今天不存在「未处理且已承接」的报警行)。 这是正确行为而非未生效;待业务侧为未处理报警建单后,该设备才会由 ALARM 变 WORK_ORDER。

既有失败(与本票零交集)

zksy-system 全量另有 2 失败 / 1 错误:AlarmLifecycleServiceTest.insertWritesLogBeforeCommittingWithoutTrigger、 WorkOrderServiceImplTest.cancelDoesNotWriteSuccessLogWhenStatusChangesConcurrently / cancelAllowsOnlyOrdersAwaitingDispatchOrAcceptance。已把本票源码整体 stash 后复跑, 同样 2 失败/1 错误、逐条相同 → 确认为 HEAD 级既有失败。

下一步

无。本票交付物已闭环,前端消费侧无需跟随改动。