docs(audit): AlarmTracking.md — accuracy + orphan resolution
ORPHAN DECISION: Keep as live doc (path: keep-and-fix). Rationale: the file carries unique v2 current content describing the alarms-over-gateway epic architecture; docs/ScriptedAlarms.md cross-references it explicitly. The orphan symptom is that docs/README.md still indexes docs/v1/AlarmTracking.md — wiring this top-level file into README.md is a follow-up task. STRUCTURAL (dimension 2): - docs/AlarmTracking.md line 138: Security.md → security.md (CASE-MISMATCH from links-report.md rows 1–2). Verified: docs/security.md exists (inode 77517627); docs/Security.md is the same file on APFS case-insensitive FS, but the checker requires exact on-disk casing. check_links.py: zero rows for docs/AlarmTracking.md after fix. CODE-REALITY (dimension 4): - line 16 table: `Phase7EngineComposer` / `Phase7EngineComposer.RouteToHistorianAsync` → no such class exists. Real class is `Phase7Composer` (src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Composer.cs). Scripted-alarm historian routing goes through ScriptedAlarmActor → HistorianAdapterActor → IAlarmHistorianSink, not a RouteToHistorianAsync method. Fixed to: Phase7Composer / ScriptedAlarmActor transitions → HistorianAdapterActor → IAlarmHistorianSink. - lines 107–123 "Historian write-back" section: referenced `Phase7Composer.ResolveHistorianSink` (method doesn't exist in current Phase7Composer.cs), `GalaxyProxyDriver` / `GalaxyHistorianWriter` (retired in PR 7.2 — no such class in codebase), and `aahClientManaged` as a direct call (now mediated through WonderwareHistorianClient). Current architecture: NullAlarmHistorianSink default registered in ServiceCollectionExtensions.AddOtOpcUaRuntime(); production override is SqliteStoreAndForwardSink wrapping WonderwareHistorianClient; bridge is HistorianAdapterActor (src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Historian/ HistorianAdapterActor.cs). Section rewritten to match code reality. - line 108: "Program.cs" as NullAlarmHistorianSink registration site → actual site is ServiceCollectionExtensions.cs, not Program.cs. STALE-STATUS (dimension 3): no blocked/pending/not-yet banners found in the top-level file; it was already written as current-state fact. Galaxy native alarms work end-to-end (verified 2026-05-31) and the doc correctly describes that as delivered. CODE-BUG-FLAGS: none. All stale references were doc-side errors; the production code is correct. UNVERIFIABLE CLAIMS: AlarmConditionService, DriverNodeManager, ConditionSink, DriverAlarmSourceAcknowledger, DriverWritableAcknowledger — these are mentioned by name in the doc but their .cs files were not found in the search. They may live under a path not searched, or may be internal implementation details within existing files. These claims are plausible given the architecture and were not changed.
This commit is contained in:
+20
-18
@@ -13,7 +13,7 @@ historical reference.
|
||||
|----------------------------------|--------------------------|------|
|
||||
| **Galaxy MxAccess (driver-native)** | `GalaxyDriver : IAlarmSource` | gateway → worker → MxAccess alarm sink → `MX_EVENT_FAMILY_ON_ALARM_TRANSITION` → `EventPump` → driver `OnAlarmEvent` → `AlarmConditionService` |
|
||||
| **Galaxy sub-attribute fallback** | `IWritable` writes to `$Alarm*` sub-attributes | gateway data subscription → driver `OnDataChange` → `DriverNodeManager` ConditionSink → `AlarmConditionService` |
|
||||
| **Scripted alarms** | `Phase7EngineComposer` | server-side script evaluator → `Phase7EngineComposer.RouteToHistorianAsync` + `AlarmConditionService` |
|
||||
| **Scripted alarms** | `Phase7Composer` | server-side script evaluator → `ScriptedAlarmActor` transitions → `HistorianAdapterActor` → `IAlarmHistorianSink` |
|
||||
|
||||
All three converge on the alarm-state actor — in v2 the OPC UA Part 9 state
|
||||
machine lives inside `ScriptedAlarmActor`
|
||||
@@ -104,23 +104,25 @@ calls.
|
||||
Scripted alarms (and any future non-Galaxy `IAlarmSource` like
|
||||
AB CIP ALMD) route to AVEVA Historian via the Wonderware sidecar:
|
||||
|
||||
- `Phase7Composer.ResolveHistorianSink` resolves an
|
||||
`IAlarmHistorianWriter` from either a driver that natively
|
||||
implements it or the DI-registered `WonderwareHistorianClient`
|
||||
(the sidecar IPC client). Driver-provided wins when both are
|
||||
present.
|
||||
- `IAlarmHistorianSink` is the DI-registered intake contract. The
|
||||
default binding is `NullAlarmHistorianSink` (registered in
|
||||
`ServiceCollectionExtensions.AddOtOpcUaRuntime`). Production
|
||||
deployments override it with `SqliteStoreAndForwardSink` wrapping
|
||||
`WonderwareHistorianClient` (the AVEVA Historian sidecar IPC client)
|
||||
— see [ServiceHosting.md](ServiceHosting.md) for the sidecar setup.
|
||||
- `SqliteStoreAndForwardSink` queues each transition to a local
|
||||
SQLite database and drains in the background via the resolved
|
||||
writer. **The durability guarantee is bounded**: the queue capacity
|
||||
defaults to 1,000,000 rows; under a sustained historian outage,
|
||||
older non-dead-lettered rows are evicted (oldest first) to make
|
||||
room for new events. The `HistorianSinkStatus.EvictedCount` counter
|
||||
surfaces lifetime eviction events to the Admin UI
|
||||
`/alarms/historian` diagnostics page so operators can detect silent
|
||||
data loss without log scraping.
|
||||
- Sidecar (PR C.1 + C.2) forwards the events to `aahClientManaged`'s
|
||||
alarm-event write API; the live SDK call site is pinned during
|
||||
PR D.1's deploy-rig validation.
|
||||
SQLite database and drains in the background via an
|
||||
`IAlarmHistorianWriter`. **The durability guarantee is bounded**: the
|
||||
queue capacity defaults to 1,000,000 rows; under a sustained
|
||||
historian outage, older non-dead-lettered rows are evicted (oldest
|
||||
first) to make room for new events. The `HistorianSinkStatus.EvictedCount`
|
||||
counter surfaces lifetime eviction events so operators can detect
|
||||
silent data loss without log scraping.
|
||||
- `HistorianAdapterActor`
|
||||
(`src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Historian/HistorianAdapterActor.cs`)
|
||||
bridges Akka cluster messages from `ScriptedAlarmActor` into the
|
||||
sink's `EnqueueAsync`; fire-and-forget so the actor loop is never
|
||||
blocked on historian reachability.
|
||||
|
||||
Galaxy-native alarms with `$Alarm*` extensions reach AVEVA Historian
|
||||
directly via System Platform's `HistorizeToAveva` toggle on the
|
||||
@@ -133,4 +135,4 @@ exclusively for non-Galaxy alarm producers.
|
||||
- v1 archive: [docs/v1/AlarmTracking.md](v1/AlarmTracking.md)
|
||||
- Galaxy driver: [docs/drivers/Galaxy.md](drivers/Galaxy.md)
|
||||
- Phase 7 scripting + alarming: [docs/v2/implementation/phase-7-scripting-and-alarming.md](v2/implementation/phase-7-scripting-and-alarming.md)
|
||||
- Security + ACL: [docs/Security.md](Security.md)
|
||||
- Security + ACL: [docs/security.md](security.md)
|
||||
|
||||
Reference in New Issue
Block a user