IHostConnectivityProbe / DriverHostStatus: dead surface — build the publisher or delete it #521

Open
opened 2026-07-27 18:55:13 -04:00 by dohertj2 · 0 comments
Owner

Split out of deferment.md §3.2 / Gitea #518. The IRediscoverable half of #518 is fixedDriverInstanceActor now consumes it and surfaces a re-browse prompt on /hosts. This tracks the other half, which is a keep-or-delete decision, not a bug.

What is true today

  • IHostConnectivityProbe is implemented by 11 drivers (Modbus, FOCAS, TwinCAT, OpcUaClient, AbLegacy, S7, Sql, Galaxy, MTConnect, Mqtt, AbCip).
  • GetHostStatuses() has zero production call sites. The only non-driver references are the interface declaration and a comment in UnwrappedCapabilityCallAnalyzer explaining why the analyzer exempts it.
  • OnHostStatusChanged has exactly one += in src/GalaxyDriver.cs:221, which is intra-driver (its aggregator re-raising onto its own interface). Every other subscription is in tests/.
  • The DriverHostStatus entity + DbSet + table exist and nothing ever writes a row. Every DriverHostStatuses reference in the repo is the DbSet declaration plus DriverHostStatusTests.
  • The entity's own doc-comment describes a component that does not exist: "The publisher hosted service on the Server side subscribes to every registered driver's OnHostStatusChanged and upserts rows on transitions + periodic liveness heartbeats."
  • DriverInstanceResilienceStatus.cs:12 claims "The Admin UI left-joins this table on DriverHostStatus for display" — that join exists in no razor file.

There is no permanently-empty UI table. /hosts reads Akka membership, IDriverStatusSnapshotStore and ConfigDB ClusterNodes/DriverInstances — never DriverHostStatus. So the dead surface is invisible: an empty table, an unused DbSet, and 11 driver implementations of a method nobody calls.

The decision

Do not delete on inference. The table was re-created in the v3 initial migration (20260715230637_V3Initial.cs:108-121), so someone carried it forward deliberately. Confirm intent first.

Either:

(a) Build the missing publisher. A hosted service subscribing to every registered driver's OnHostStatusChanged, upserting DriverHostStatus rows on transition plus a liveness heartbeat, and a /hosts section that reads them. This is what the entity doc already describes. Note the two halves are separable — OnHostStatusChanged (the event) is the useful half; GetHostStatuses() (the snapshot pull) is only needed to prime state at startup.

(b) Delete it. Drop GetHostStatuses() from the interface, the 11 driver implementations, the DbSet, the table (migration), and DriverHostStatusTests. Fix the two doc-comments that describe the non-existent publisher and the non-existent Admin UI join.

Per-host connectivity is genuinely useful for a multi-device driver (a FOCAS or AbLegacy instance owning several PLCs), where today one unreachable device is invisible behind an otherwise-Healthy driver row. That is the argument for (a).

Split out of `deferment.md` §3.2 / Gitea #518. The `IRediscoverable` half of #518 is **fixed** — `DriverInstanceActor` now consumes it and surfaces a re-browse prompt on `/hosts`. This tracks the other half, which is a **keep-or-delete decision, not a bug**. ## What is true today - `IHostConnectivityProbe` is implemented by **11 drivers** (Modbus, FOCAS, TwinCAT, OpcUaClient, AbLegacy, S7, Sql, Galaxy, MTConnect, Mqtt, AbCip). - `GetHostStatuses()` has **zero production call sites**. The only non-driver references are the interface declaration and a comment in `UnwrappedCapabilityCallAnalyzer` explaining why the analyzer exempts it. - `OnHostStatusChanged` has exactly one `+=` in `src/` — `GalaxyDriver.cs:221`, which is intra-driver (its aggregator re-raising onto its own interface). Every other subscription is in `tests/`. - The `DriverHostStatus` entity + DbSet + table exist and **nothing ever writes a row**. Every `DriverHostStatuses` reference in the repo is the DbSet declaration plus `DriverHostStatusTests`. - The entity's own doc-comment describes a component that does not exist: *"The publisher hosted service on the Server side subscribes to every registered driver's `OnHostStatusChanged` and upserts rows on transitions + periodic liveness heartbeats."* - `DriverInstanceResilienceStatus.cs:12` claims *"The Admin UI left-joins this table on DriverHostStatus for display"* — that join exists in no razor file. **There is no permanently-empty UI table.** `/hosts` reads Akka membership, `IDriverStatusSnapshotStore` and ConfigDB `ClusterNodes`/`DriverInstances` — never `DriverHostStatus`. So the dead surface is invisible: an empty table, an unused DbSet, and 11 driver implementations of a method nobody calls. ## The decision **Do not delete on inference.** The table was *re-created* in the v3 initial migration (`20260715230637_V3Initial.cs:108-121`), so someone carried it forward deliberately. Confirm intent first. Either: **(a) Build the missing publisher.** A hosted service subscribing to every registered driver's `OnHostStatusChanged`, upserting `DriverHostStatus` rows on transition plus a liveness heartbeat, and a `/hosts` section that reads them. This is what the entity doc already describes. Note the two halves are separable — **`OnHostStatusChanged` (the event) is the useful half**; `GetHostStatuses()` (the snapshot pull) is only needed to prime state at startup. **(b) Delete it.** Drop `GetHostStatuses()` from the interface, the 11 driver implementations, the DbSet, the table (migration), and `DriverHostStatusTests`. Fix the two doc-comments that describe the non-existent publisher and the non-existent Admin UI join. Per-host connectivity is genuinely useful for a multi-device driver (a FOCAS or AbLegacy instance owning several PLCs), where today one unreachable device is invisible behind an otherwise-Healthy driver row. That is the argument for (a).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#521