fix(scada): verify recovery after replay work-order completion
Generic Container CI/CD / test-build-publish (push) Successful in 3m58s
Server CI/CD v2 / build-test-publish-and-deploy (push) Successful in 3m58s

This commit is contained in:
2026-11-07 23:12:42 +08:00
parent 06d8539aa8
commit 2a7b96f813
7 changed files with 61 additions and 10 deletions
+4 -2
View File
@@ -20,8 +20,7 @@ RECOVERY_WORKFLOWS = {"burst_report", "scada_anomaly"}
def track_work_order(task: dict, action: dict) -> None:
if (task.get("workflow") not in RECOVERY_WORKFLOWS or action["kind"] != "create_work_order"
or task.get("source", {}).get("replay_context")):
if task.get("workflow") not in RECOVERY_WORKFLOWS or action["kind"] != "create_work_order":
return
receipt = action.get("receipt") or {}
if action.get("execution_status") != "succeeded" or receipt.get("adapter") != "peripheral_sample":
@@ -160,6 +159,9 @@ async def reconcile_recoveries(service: OperationalTaskService, timescale: Async
devices.extend(row["device_id"] for row in data if isinstance(row, dict) and isinstance(row.get("device_id"), str))
devices = list(dict.fromkeys(devices))
async with timescale.transaction():
# Field completion authorizes a separate recovery observation even
# when the incident was found in a frozen replay. Keep that replay's
# query window and batch boundary unchanged.
rows = await ScadaRepository.get_recovery_scada_readings(
timescale, devices, incident_at, returned_at, through, baseline_limit=100_001,
) if through > returned_at and devices else []