OpcUaClient respawn replays inactive+unacked conditions as Raise+Clear (duplicate rows, Active flicker) #657
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found in the #656 review (batch hw3). Pre-existing, outside #656's scope.
OpcUaClientDriver.cs~2114-2116). That writes a duplicate "Activated" + "Cleared"/alertspair, and clients briefly see the condition Active again.OpcUaClientDriver.cs~1946-1955) still writes a stray "Activated" row, and the server's state does not change.Fix direction: mirror #656. Add an atomic
InactiveUnacknowledgedtransition (one projector update, one client event, rows only for what changed), carryIsRestatementon first sight, and give an inactive+acked first sight a no-row path. Prove it with an end-to-end test throughDriverHostActor.ForwardNativeAlarm, and with the opc-plc respawn live check from hw3 (scratchpadrecipe in the #656 comment).Extra detail from #658 (closed as a duplicate of item 2): the first-sight inactive+acked event is emitted as
AlarmTransitionKind.Unspecified, not a flaggedClear. So (a) a host condition retained Active across the respawn stays Active — nothing clears it — and (b) with no active prior the projector's default branch writes an "Activated" row for an inactive alarm. Expected: a flagged (IsRestatement) Clear — no row when the host condition is already inactive, a real Clear when it was retained Active. Note: since #611 the projector also has a third no-row rule (flaggedUnspecifiedmoves message/severity without a row), which OpcUaClient first-sight-after-respawn can reach; keep it consistent when fixing this. Live recipe: see the #656 comment.Fixed and pushed in master
ea220363(mergeea220363, branch commits48a80b59,24eed8ad).AlarmTransitionKind.InactiveUnacknowledgedmoves a condition to inactive+unacked in ONE projection, writing rows only for what changed (Activated+Cleared from an acked prior, Cleared from Active+unacked, nothing if already inactive+unacked). OpcUaClient uses it instead of Raise/Retrigger+Clear, so clients no longer see an Active flicker and respawns no longer duplicate rows.Unspecified; a flagged Acknowledge on an already-acked condition writes no row. A host that retained the condition Active now gets a real Cleared.Galaxy/FOCAS/MTConnect/AbCip paths unchanged (they never emit the new kind or a flagged Ack). 4 new E2E tests through
DriverHostActor.ForwardNativeAlarm(all fail with either the projector or driver change reverted).Live gate (docker-dev, chained via central's mirror of opc-plc NorthMotor/Yellow, held inactive+unacked): old image — every respawn showed a brief Active and wrote a duplicate Activated+Cleared pair (3/3); new image — 4 respawns, no Active event, no rows; a real re-activation still wrote its Activated row; retained-Active variant wrote exactly one Cleared. Item 2 is E2E-only (a Part 9 server never replays inactive+acked on refresh). Independent Opus review: MERGE. Full suite 13214 passed / 0 failed.
Residual (pre-existing, documented in AlarmTracking.md): a cold host treats an unseen condition as acked, so after a node restart each upstream inactive+unacked condition still writes one Activated+Cleared pair. Separate bug found during the gate filed as #662 (alarm feed not restored on a non-respawning deploy / reconcile).