Galaxy reconnect snapshot: ActiveAcked entry for an unknown condition lands inactive; re-statements write duplicate Activated rows #656

Closed
opened 2026-10-08 20:51:50 -04:00 by dohertj2 · 1 comment
Owner

Residuals noted in the #647 reviews (batch b647), pre-existing, out of that lane:

  1. After a process restart, a Galaxy reconnect-snapshot entry that is Active and already acknowledged maps to Acknowledge only. On a condition the host has no prior record of, that leaves it inactive+acked instead of Active+acked.
  2. OpcUaClient and the Galaxy snapshot re-stating a condition that is already Active and unacked send Retrigger, which writes a second 'Activated' /alerts row (the old Raise did the same).
    Fix direction: map ActiveAcked-on-unknown to Raise+Acknowledge (or a combined transition the projector understands), and let the projector treat a Retrigger with an unchanged message on an Active+unacked condition as a re-statement for history purposes.
Residuals noted in the #647 reviews (batch b647), pre-existing, out of that lane: 1. After a process restart, a Galaxy reconnect-snapshot entry that is Active **and already acknowledged** maps to `Acknowledge` only. On a condition the host has no prior record of, that leaves it inactive+acked instead of Active+acked. 2. OpcUaClient and the Galaxy snapshot re-stating a condition that is already Active and **unacked** send Retrigger, which writes a second 'Activated' /alerts row (the old Raise did the same). Fix direction: map ActiveAcked-on-unknown to Raise+Acknowledge (or a combined transition the projector understands), and let the projector treat a Retrigger with an unchanged message on an Active+unacked condition as a re-statement for history purposes.
Author
Owner

Fixed on master — merge 82750ccc (lane commit e138e397 + predecessor), pushed 2026-10-09.

  • New atomic AlarmTransitionKind.ActiveAcknowledged (one projector update, one client event, /alerts rows only for what changed) — Galaxy snapshot ActiveAcked and OpcUaClient inactive→acked-active. A cold host's ActiveAcked entry now lands Active.
  • New optional AlarmEventArgs.IsRestatement (Galaxy snapshot entries, OpcUaClient first sight): a flagged Retrigger on an Active+unacked condition with the same message and severity, or a flagged Clear on an inactive condition, writes no row. NativeAlarmProjector returns the rows to write; FOCAS/MTConnect/AbCip unaffected. E2E: Runtime.Tests/NativeAlarmRestatementEndToEndTests.

Live check (docker-dev + opc-plc), reusable for #657:

  1. ssh dohertj2@10.100.0.35 'cd /opt/otopcua-opcuaclient && docker compose up -d' (bring it down again after).
  2. Insert raw tag MAIN-opcua-alarm1 on the MAIN OpcUaClient driver with TagConfig {"nodeId":"ns=6;s=1:Colours/NorthMotor?Red","alarm":{"alarmType":"AlarmCondition","severity":500}}, deploy (docker-dev/deploy.sh < /dev/null). That condition is permanently Active+unacked and alternates its message every few seconds.
  3. Force respawns: UPDATE dbo.DriverInstance SET DriverConfig = JSON_MODIFY(DriverConfig,'$.hw3RespawnToggle',N) + deploy, every ~15 s (logs: stopped driver child MAIN-opcua → spawned → connected).
  4. Watch AdminUI /alerts: a duplicate re-statement is a row identical in timestamp/severity/message to the one before it.

Result: pre-fix image 4/4 respawns wrote a duplicate "Activated" row; post-fix 0/6. Revert the tag/toggle afterwards.

Follow-up found in review: #657 (respawn replays inactive+unacked as Raise+Clear).

Fixed on master — merge `82750ccc` (lane commit `e138e397` + predecessor), pushed 2026-10-09. - New atomic `AlarmTransitionKind.ActiveAcknowledged` (one projector update, one client event, `/alerts` rows only for what changed) — Galaxy snapshot `ActiveAcked` and OpcUaClient inactive→acked-active. A cold host's ActiveAcked entry now lands Active. - New optional `AlarmEventArgs.IsRestatement` (Galaxy snapshot entries, OpcUaClient first sight): a flagged Retrigger on an Active+unacked condition with the same message and severity, or a flagged Clear on an inactive condition, writes no row. `NativeAlarmProjector` returns the rows to write; FOCAS/MTConnect/AbCip unaffected. E2E: `Runtime.Tests/NativeAlarmRestatementEndToEndTests`. **Live check (docker-dev + opc-plc), reusable for #657:** 1. `ssh dohertj2@10.100.0.35 'cd /opt/otopcua-opcuaclient && docker compose up -d'` (bring it down again after). 2. Insert raw tag `MAIN-opcua-alarm1` on the MAIN OpcUaClient driver with TagConfig `{"nodeId":"ns=6;s=1:Colours/NorthMotor?Red","alarm":{"alarmType":"AlarmCondition","severity":500}}`, deploy (`docker-dev/deploy.sh < /dev/null`). That condition is permanently Active+unacked and alternates its message every few seconds. 3. Force respawns: `UPDATE dbo.DriverInstance SET DriverConfig = JSON_MODIFY(DriverConfig,'$.hw3RespawnToggle',N)` + deploy, every ~15 s (logs: `stopped driver child MAIN-opcua` → `spawned` → `connected`). 4. Watch AdminUI `/alerts`: a duplicate re-statement is a row identical in timestamp/severity/message to the one before it. Result: pre-fix image 4/4 respawns wrote a duplicate "Activated" row; post-fix 0/6. Revert the tag/toggle afterwards. Follow-up found in review: #657 (respawn replays inactive+unacked as Raise+Clear).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#656