feat(drivers): periodic reconcile of desired vs actual driver subscriptions #488

Open
opened 2026-07-21 03:36:41 -04:00 by dohertj2 · 0 comments
Owner

Raised while reviewing the #485 subscription guard: is there a way to periodically check for actual subscriptions, to defend against races or a subscription dying silently?

What exists today

  • DriverInstanceActor holds _desiredRefs and re-asserts them on every Connected entry (ResubscribeDesired), so a reconnect self-heals.
  • A periodic 30s health-poll timer already exists — but it only calls IDriver.GetHealth() and publishes to the AdminUI. It never touches subscriptions.
  • ISubscriptionHandle is opaque (just a DiagnosticId string), so the Core currently cannot ask a driver what it is actually subscribed to.

The gap

Nothing detects a subscription that dies while the driver remains Connected — a server-side subscription drop, a session reset the driver does not surface as a disconnect, or a handle lost to an error path. The desired set is only re-applied on a connect transition or a deploy.

Two options

A — cheap, no interface change. A periodic invariant check in DriverInstanceActor: while Connected, if _desiredRefs.Count > 0 but _subscriptionHandle is null, self-tell Subscribe. This is a state-machine consistency check, not a true probe, but it needs no driver support and could ride the existing health-poll tick.

B — real reconcile, needs an interface change. Add a member to ISubscribable (e.g. Task<IReadOnlyList<string>> GetSubscribedRefsAsync()), or liveness on ISubscriptionHandle, then periodically diff desired vs actual and re-subscribe the difference. Requires implementing it across all 7 drivers (Modbus, S7, AB CIP/Legacy, TwinCAT, FOCAS, OpcUaClient) plus Galaxy, each with different subscription mechanics (polled vs native).

Suggest A first — it is small and strictly additive — and only take B if a real occurrence shows the handle is present but dead.

Explicitly NOT this issue

This does not address deploy-time drift, which was #486 (a node claiming a revision it never applied). Re-asserting a desired set that is already correct would not have helped there. Keep the two separate.

Raised while reviewing the #485 subscription guard: is there a way to periodically check for actual subscriptions, to defend against races or a subscription dying silently? ## What exists today - `DriverInstanceActor` holds `_desiredRefs` and re-asserts them on every **Connected** entry (`ResubscribeDesired`), so a reconnect self-heals. - A periodic 30s `health-poll` timer already exists — but it only calls `IDriver.GetHealth()` and publishes to the AdminUI. It never touches subscriptions. - `ISubscriptionHandle` is **opaque** (just a `DiagnosticId` string), so the Core currently cannot ask a driver what it is actually subscribed to. ## The gap Nothing detects a subscription that dies while the driver remains Connected — a server-side subscription drop, a session reset the driver does not surface as a disconnect, or a handle lost to an error path. The desired set is only re-applied on a connect transition or a deploy. ## Two options **A — cheap, no interface change.** A periodic invariant check in `DriverInstanceActor`: while Connected, if `_desiredRefs.Count > 0` but `_subscriptionHandle is null`, self-tell `Subscribe`. This is a state-machine consistency check, not a true probe, but it needs no driver support and could ride the existing `health-poll` tick. **B — real reconcile, needs an interface change.** Add a member to `ISubscribable` (e.g. `Task<IReadOnlyList<string>> GetSubscribedRefsAsync()`), or liveness on `ISubscriptionHandle`, then periodically diff desired vs actual and re-subscribe the difference. Requires implementing it across all 7 drivers (Modbus, S7, AB CIP/Legacy, TwinCAT, FOCAS, OpcUaClient) plus Galaxy, each with different subscription mechanics (polled vs native). Suggest A first — it is small and strictly additive — and only take B if a real occurrence shows the handle is present but dead. ## Explicitly NOT this issue This does not address deploy-time drift, which was #486 (a node claiming a revision it never applied). Re-asserting a desired set that is already correct would not have helped there. Keep the two separate.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#488