docs: the stale-Good quality contract, stated once (R3-02)
This commit is contained in:
@@ -297,7 +297,32 @@ non-`Healthy` state **and** its `LastSuccessfulRead` has been frozen for 90 s. T
|
||||
system — it is a local `GetHealth()` read, and only reaches the network once a driver has already stopped
|
||||
reading.
|
||||
|
||||
See `docs/DriverLifecycle.md` §"The comms-loss watchdog".
|
||||
- **What comms loss now does downstream — one contract, six seams (archreview R3-02).** "A value consumer
|
||||
never reports a quality better than its source's" is stated once in `docs/DriverLifecycle.md` §"The
|
||||
quality contract" and implemented by `Core.Abstractions.InputQuality` (`WorstOf`/`IsUsable`). Three
|
||||
things changed with it, all client-visible:
|
||||
- ⚠️ **Value nodes of a comms-lost driver now go Bad.** `DriverHostActor.FanCommsLossToValueNodes`
|
||||
stamps `BadNoCommunication` on the raw NodeId **and every referencing UNS NodeId**, **value retained**,
|
||||
via the new status-only sink primitive `IOpcUaAddressSpaceSink.WriteStatuses` (the host holds no value
|
||||
cache, so only the node can keep the value). #481 had wired comms loss to the mux and to Part 9
|
||||
conditions and stopped one seam short of the external data plane. A consumer that treats Bad as "drop
|
||||
the tag" (ScadaBridge) will see more Bads — that is the fix working.
|
||||
- **Nothing Good is written on reconnect** — recovery is the driver's own re-publish (the poll engine's
|
||||
`forceRaise`, MQTT's new initial push). Instead the host **audits**: refs still latched 30 s after a
|
||||
reconnect log a Warning and increment `otopcua.driver.comms_latched_refs`. Non-zero on that counter
|
||||
means a driver reconnects without re-publishing.
|
||||
- **Every dedup on the recovery path is keyed on (value, status), not value.** A device that comes back
|
||||
usually comes back holding the same reading, so a value-only dedup swallows the recovery and the node
|
||||
stays Bad forever — the v3-gate trap, now closed in the Calculation driver, the virtual-tag actor and
|
||||
(via a connection-loss stale) MQTT's plain-mode suppression. **Any new consumer of driver values must
|
||||
repeat this**; a regression test for it must replay the IDENTICAL value or it proves nothing.
|
||||
- Consequences per seam: MQTT/Sparkplug stale on connection loss and push cached snapshots on every
|
||||
(re)subscribe (`docs/drivers/Mqtt.md`); the Calculation driver and virtual tags **hold** while any
|
||||
input is Bad and inherit the worst input's sub-code, evaluate through Uncertain, and hand scripts the
|
||||
input's real `StatusCode`/`SourceTimestampUtc` (`docs/drivers/Calculation.md`, `docs/ScriptEditor.md`)
|
||||
— so a script that relied on receiving `null` for a dead input no longer runs at all while it is Bad.
|
||||
|
||||
See `docs/DriverLifecycle.md` §"The comms-loss watchdog" and §"The quality contract".
|
||||
|
||||
## mxaccessgw
|
||||
|
||||
|
||||
Reference in New Issue
Block a user