fix(historian): preserve stable alarm delivery identities
This commit is contained in:
@@ -153,6 +153,19 @@ Ordering follows from that: the drain reads in `enqueued_at_utc` order (with `id
|
||||
as a tiebreak so the ordering is total), because a hashed key carries no
|
||||
insertion sequence.
|
||||
|
||||
Gateway delivery carries a separate nonzero `DeliveryId` GUID. Direct event instances
|
||||
create it once; retries and record copies preserve it. It is excluded from queue JSON
|
||||
and business equality, so the existing payload fingerprint and pair deduplication stay
|
||||
unchanged. The drain derives its delivery GUID solely from the persisted row `id`,
|
||||
including migrated legacy rows. It never hashes a reconstructed payload or mints an ID
|
||||
per send. The versioned encoding in `AlarmDeliveryIds` therefore survives retry,
|
||||
restart, payload edits and replicated failover without a schema migration.
|
||||
|
||||
Different business payloads at the same timestamp remain distinct; completely identical
|
||||
payloads deliberately converge. An explicitly empty direct delivery ID is rejected.
|
||||
The Gateway mapper sends this GUID as the wire event ID; the live alarm readback test
|
||||
requires that exact ID. SQL Server and QuestDB retain their existing event-ID schemes.
|
||||
|
||||
`EnqueueAsync` does a single `INSERT … ON CONFLICT DO NOTHING` on the hot path.
|
||||
To avoid a `SELECT COUNT(*)` on every enqueue, the sink keeps an in-memory
|
||||
non-dead-lettered row counter (seeded at startup, kept current by every mutation,
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# Alarm delivery identity results — lmxopcua #705
|
||||
|
||||
Alarm events now carry a nonzero delivery GUID created once for direct delivery and preserved across retries and record copies. It is excluded from queue JSON and business-field equality/hash. Queued delivery overrides it with a frozen versioned UUID encoding derived only from the persisted queue row key, preserving existing payload JSON, fingerprints, schema, deduplication and AlarmId. The Gateway mapper sends that GUID and rejects explicitly empty identities. SQL Server and QuestDB identity logic is unchanged.
|
||||
|
||||
Coverage includes literal historical JSON/fingerprint/GUID vectors; ten-field equality and hash behavior; direct copies/retries; queue retry/reopen/payload edits/dead-letter revival; identical-input convergence; distinct same-time business events; real replicated queue convergence; and legacy migration. Reconstructed direct objects receive new identities; durable reconstruction uses the queue. Completely identical business payloads remain intentionally deduplicated.
|
||||
|
||||
TDD: direct wire regression failed on an empty ID; queued retry/reopen regression failed on changing IDs. Final affected runs: Core51/51, Host migration/convergence16/16, Gateway453passed/6live skipped/0failed. Full offline solution:14,635passed/611skipped/0failed across62suites, exit0. Independent final review and diffcheck clear. Fixture configuration variables were removed before all runs.
|
||||
|
||||
No live event writes, deployed sender rollout or historical row rewrite occurred. The live round-trip test now requires exact delivery GUID readback; actual persistence remains the open Gateway #28 gate, alongside its separate #39 timestamp-offset provider failure. Upstream History controls #29 and lmxopcua #694/#700 remain open.
|
||||
Reference in New Issue
Block a user