Auto: ablegacy-12 — auto-demote on comm failure

Closes #255
This commit is contained in:
Joseph Doherty
2026-04-26 08:44:53 -04:00
parent 8ee65a75d2
commit 1e3053c0d8
18 changed files with 1160 additions and 31 deletions

View File

@@ -53,12 +53,31 @@ supplies a `FakeAbLegacyTag`.
counters: 5 reads (3 ok / 2 fail) → `RequestCount=5`, `ResponseCount=3`,
`ErrorCount=2`; `LastErrorCode` reflects the most recent libplctag status;
`RetryCount` increments per retry attempt beyond the first; counters reset
on `ReinitializeAsync`; discovery emits exactly 7 diagnostic variables per
device under `_Diagnostics/`; collision rejection at `InitializeAsync` for
user tags shadowing reserved names or `_Diagnostics/` addresses; the
`_Diagnostics/<host>/<name>` short-circuit returns the live snapshot through
`ReadAsync` without bumping `RequestCount`; two devices keep counters
independent.
on `ReinitializeAsync`; discovery emits the canonical diagnostic variables
per device under `_Diagnostics/` (now 9 with PR ablegacy-12); collision
rejection at `InitializeAsync` for user tags shadowing reserved names or
`_Diagnostics/` addresses; the `_Diagnostics/<host>/<name>` short-circuit
returns the live snapshot through `ReadAsync` without bumping
`RequestCount`; two devices keep counters independent.
- `AbLegacyAutoDemoteTests`**PR ablegacy-12 / #255** auto-demote on comm
failure: 3 consecutive failures arm the demote window and surface
`HostState.Demoted`; subsequent reads short-circuit with
`BadCommunicationError` *without invoking libplctag* (verified via
`factory.Tags["N7:0"].ReadCount` not advancing); successful read resets
the consecutive-failure counter; failure-success-failure pattern doesn't
cross the threshold; `DemoteCount` + `LastDemotedUtc` surface via
`_Diagnostics/`; `Enabled=false` opts out (failures still count, demotion
never fires); `ReinitializeAsync` clears the active window but preserves
cumulative `DemoteCount`; cool-down expiry allows the next read through;
two devices in one driver — one faulty, one healthy — proves the faulty
side's demotion doesn't starve the healthy side; `BadNodeIdUnknown`
(terminal) does not count toward the comm-failure tally; DTO JSON
round-trip preserves `FailureThreshold` / `DemoteForMs` / `Enabled` at
the per-device level; `HostState.Demoted` enum value is wired through
`Core.Abstractions`. Companion integration test in
`tests/.../IntegrationTests/AbLegacyAutoDemoteTests.cs` runs the
two-device-one-unreachable scenario against a live ab_server fixture
using `127.0.0.1:1` as the unreachable peer.
- `RsLogixSymbolImportTests` — ablegacy-11 / #254 RSLogix CSV symbol-import parser:
canonical 8-row CSV (one row per N/F/B/L/ST/T/C/R) → 8 typed
`AbLegacyTagDefinition`s with the right `DataType`; header + comment-line