Driver stability tiers are inert: every driver runs Tier A — pass real tiers or delete the machinery #522

Closed
opened 2026-07-27 19:54:08 -04:00 by dohertj2 · 1 comment
Owner

Split out of deferment.md §3.3 / §8.6. Decision taken 2026-07-27: document the truth now, defer the code decision here — no runtime behaviour was changed, because turning dormant recycle machinery on for two live drivers deserves its own live gate rather than arriving as a side effect of a docs pass.

What is true today

  • DriverFactoryRegistry takes DriverTier tier = DriverTier.A, and no factory in src/Drivers/ passes a tier. All 12 drivers run Tier A.
  • The Tier-C-only protections have therefore never engaged:
    • MemoryRecycle gates on when _tier == DriverTier.C.
    • ScheduledRecycleScheduler refuses unless Tier C.
    • IDriverSupervisor has zero implementations — yet the config parser still validates RecycleIntervalSeconds, so an operator can author a recycle interval that does nothing.
  • DriverTypeRegistry is vestigial: referenced only by DriverTypeRegistryTests. Nothing registers metadata at startup, nothing validates DriverInstance.DriverType against it, and its AllowedNamespaceKinds field was retired with the v3 Namespace entity.
  • The separate-Windows-service hosting docs/v2/driver-stability.md describes for Tier C does not exist. Galaxy reaches MXAccess over gRPC to the external mxaccessgw sidecar (the Galaxy.Proxy/Host/Shared pattern retired in PR 7.2); FOCAS runs in-process since its managed wire client landed 2026-04-24.

The decision

(a) Pass real tiers. Register Galaxy and FOCAS as Tier C so MemoryRecycle and ScheduledRecycleScheduler engage. This turns on dormant recycle behaviour for two live drivers — a real runtime change that wants its own live gate (a driver being recycled under memory pressure is exactly the kind of thing that is fine in theory and disruptive in practice). Note the tier model also assumes out-of-process isolation that no longer exists, so "Tier C" today would mean the recycle knobs only, not the isolation.

(b) Delete the machinery. Remove the tier gates, IDriverSupervisor, DriverTypeRegistry, and the recycle scheduler. Removes a documented-but-fictional capability, and stops the parser validating a knob with no effect.

Worth resolving either way: today the tier system is documented, operator-authorable, and inert — the same shape as the ACL subsystem in #520.

Already done

docs/v2/driver-stability.md carries a banner stating the tier table is aspirational and naming the dormant gates; docs/drivers/README.md already said Tier A for Galaxy and FOCAS, so the two no longer contradict each other.

Split out of `deferment.md` §3.3 / §8.6. **Decision taken 2026-07-27: document the truth now, defer the code decision here** — no runtime behaviour was changed, because turning dormant recycle machinery on for two live drivers deserves its own live gate rather than arriving as a side effect of a docs pass. ## What is true today - `DriverFactoryRegistry` takes `DriverTier tier = DriverTier.A`, and **no factory in `src/Drivers/` passes a tier**. All 12 drivers run Tier A. - The **Tier-C-only protections have therefore never engaged**: - `MemoryRecycle` gates on `when _tier == DriverTier.C`. - `ScheduledRecycleScheduler` refuses unless Tier C. - `IDriverSupervisor` has **zero implementations** — yet the config parser still validates `RecycleIntervalSeconds`, so an operator can author a recycle interval that does nothing. - `DriverTypeRegistry` is **vestigial**: referenced only by `DriverTypeRegistryTests`. Nothing registers metadata at startup, nothing validates `DriverInstance.DriverType` against it, and its `AllowedNamespaceKinds` field was retired with the v3 `Namespace` entity. - The separate-Windows-service hosting `docs/v2/driver-stability.md` describes for Tier C does not exist. Galaxy reaches MXAccess over gRPC to the external mxaccessgw sidecar (the `Galaxy.Proxy`/`Host`/`Shared` pattern retired in PR 7.2); FOCAS runs in-process since its managed wire client landed 2026-04-24. ## The decision **(a) Pass real tiers.** Register Galaxy and FOCAS as Tier C so `MemoryRecycle` and `ScheduledRecycleScheduler` engage. This turns on dormant recycle behaviour for two live drivers — a real runtime change that wants its own live gate (a driver being recycled under memory pressure is exactly the kind of thing that is fine in theory and disruptive in practice). Note the tier model also assumes out-of-process isolation that no longer exists, so "Tier C" today would mean the recycle knobs only, not the isolation. **(b) Delete the machinery.** Remove the tier gates, `IDriverSupervisor`, `DriverTypeRegistry`, and the recycle scheduler. Removes a documented-but-fictional capability, and stops the parser validating a knob with no effect. Worth resolving either way: today the tier system is documented, operator-authorable, and inert — the same shape as the ACL subsystem in #520. ## Already done `docs/v2/driver-stability.md` carries a banner stating the tier table is aspirational and naming the dormant gates; `docs/drivers/README.md` already said Tier A for Galaxy and FOCAS, so the two no longer contradict each other.
Author
Owner

Resolved on master abda6f9e — option (b), delete.

A correction to this issue first

It says the Tier-C-only protections never engaged, which implies the Tier A/B parts did. They did not. Nothing constructs MemoryTracking, MemoryRecycle or ScheduledRecycleScheduler outside their own unit tests, so the entire Core/Stability recycle layer was dead — including Tier A memory tracking.

That matters for the decision: it means option (a) was never a flag flip. "Pass real tiers" would have meant writing the wiring that never existed AND arming it, on two live drivers, at once.

Why delete rather than activate

The premise is gone, not merely unused. Tier C meant a driver running out-of-process behind an IDriverSupervisor that could restart its Host. No such process exists anywhere: Galaxy reaches MXAccess over gRPC to the external mxaccessgw sidecar (PR 7.2 retired the in-process Host/Proxy/Shared projects), and FOCAS has run in-process since 2026-04-24. Consistently, IDriverSupervisor had zero implementations — there was nothing for one to implement against. Activating the tiers would arm a recycle with nothing to recycle.

The operator-facing half went too: RecycleIntervalSeconds was authorable through the AdminUI's resilience section and validated by the parser while configuring nothing.

Deleted: MemoryTracking, MemoryRecycle, ScheduledRecycleScheduler, IDriverSupervisor, the vestigial DriverTypeRegistry, RecycleIntervalSeconds, and their tests.

What deliberately survived

  • DriverTier itself is load-bearing — do not delete it while following this issue. DriverResilienceOptions.GetTierDefaults(tier) supplies the real per-capability timeout/retry/breaker policies, resolved via DriverFactoryRegistry.GetTier and applied by DriverCapabilityInvokerFactory. Only the isolation-and-recycle layer above it is gone.
  • WedgeDetector came along in the same directory and is equally dead in production, but it is tier-agnostic and is not recycle machinery — it only shares the folder. Restored rather than swept up in a decision that was not about it.

Compatibility

A deployed ResilienceConfig blob still carrying recycleIntervalSeconds parses cleanly — unknown keys are ignored, guarded by a new test, because a blob that suddenly failed to parse would fall back to tier defaults and silently discard the operator's real timeout/retry overrides alongside the dead one. The AdminUI's preserve-unknown-keys bag also keeps the key rather than rewriting stored config on an unrelated edit; removing it is a migration decision, not a side effect of opening a page.

The 01/U-6 knob-inertness guard carried an explicit carve-out admitting this knob was dormant and out of scope. That carve-out is gone, so the expected set is now literally what the test's name claims.

Residual — filed, not folded in

IDriver.GetMemoryFootprint() and FlushOptionalCachesAsync() lose their only consumer here. Removing them touches all 12 drivers and every test stub, so they are documented as consumerless and filed as #525 rather than buried in this diff.

Docs updated: docs/v2/driver-stability.md is now marked a historical design record, and docs/DriverLifecycle.md / docs/drivers/README.md / docs/OpcUaServer.md no longer name the deleted types as live (OpcUaServer.md had credited DriverTypeRegistry as the tier authority, which it never was).

Resolved on master `abda6f9e` — **option (b), delete**. ## A correction to this issue first It says the *Tier-C-only* protections never engaged, which implies the Tier A/B parts did. **They did not.** Nothing constructs `MemoryTracking`, `MemoryRecycle` or `ScheduledRecycleScheduler` outside their own unit tests, so the entire `Core/Stability` recycle layer was dead — including Tier A memory tracking. That matters for the decision: it means option (a) was never a flag flip. "Pass real tiers" would have meant **writing the wiring that never existed AND arming it**, on two live drivers, at once. ## Why delete rather than activate The premise is gone, not merely unused. Tier C meant a driver running **out-of-process behind an `IDriverSupervisor` that could restart its Host**. No such process exists anywhere: Galaxy reaches MXAccess over gRPC to the external mxaccessgw sidecar (PR 7.2 retired the in-process Host/Proxy/Shared projects), and FOCAS has run in-process since 2026-04-24. Consistently, `IDriverSupervisor` had **zero implementations** — there was nothing for one to implement against. Activating the tiers would arm a recycle with nothing to recycle. The operator-facing half went too: `RecycleIntervalSeconds` was authorable through the AdminUI's resilience section and validated by the parser while configuring nothing. Deleted: `MemoryTracking`, `MemoryRecycle`, `ScheduledRecycleScheduler`, `IDriverSupervisor`, the vestigial `DriverTypeRegistry`, `RecycleIntervalSeconds`, and their tests. ## What deliberately survived - **`DriverTier` itself is load-bearing — do not delete it while following this issue.** `DriverResilienceOptions.GetTierDefaults(tier)` supplies the real per-capability timeout/retry/breaker policies, resolved via `DriverFactoryRegistry.GetTier` and applied by `DriverCapabilityInvokerFactory`. Only the isolation-and-recycle layer above it is gone. - **`WedgeDetector`** came along in the same directory and is equally dead in production, but it is tier-agnostic and is not recycle machinery — it only shares the folder. Restored rather than swept up in a decision that was not about it. ## Compatibility A deployed `ResilienceConfig` blob still carrying `recycleIntervalSeconds` parses cleanly — unknown keys are ignored, guarded by a new test, because a blob that suddenly *failed* to parse would fall back to tier defaults and **silently discard the operator's real timeout/retry overrides** alongside the dead one. The AdminUI's preserve-unknown-keys bag also keeps the key rather than rewriting stored config on an unrelated edit; removing it is a migration decision, not a side effect of opening a page. The 01/U-6 knob-inertness guard carried an explicit carve-out admitting this knob was dormant and out of scope. That carve-out is gone, so the expected set is now literally what the test's name claims. ## Residual — filed, not folded in `IDriver.GetMemoryFootprint()` and `FlushOptionalCachesAsync()` lose their only consumer here. Removing them touches all 12 drivers and every test stub, so they are documented as consumerless and filed as **#525** rather than buried in this diff. Docs updated: `docs/v2/driver-stability.md` is now marked a historical design record, and `docs/DriverLifecycle.md` / `docs/drivers/README.md` / `docs/OpcUaServer.md` no longer name the deleted types as live (`OpcUaServer.md` had credited `DriverTypeRegistry` as the tier authority, which it never was).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#522