feat(mesh-phase4): retire DB-reachability from ServiceLevel on DB-less nodes

Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
Joseph Doherty
2026-07-23 11:55:43 -04:00
parent 5c40908a55
commit 9565827275
4 changed files with 223 additions and 11 deletions
@@ -276,6 +276,22 @@ apply through the fetcher), so the change is defensive nullability, not new cont
1920/2096/2588 is inside a Direct-mode-only path before guarding — if any is on the shared apply path,
that is a Phase-3 gap to surface, not silently guard.
**Two specific sites the Task-2 code review surfaced (MUST be handled here):**
- **Remove the interim `dbFactory!` at `ServiceCollectionExtensions.cs:~470`** (added in Task 2 to preserve
compilation) — once `DriverHostActor._dbFactory` is nullable, pass the plain (nullable) `dbFactory`.
- **`UpsertNodeDeploymentState` (2613-2643) is called UNCONDITIONALLY on the FetchAndCache apply path**
(`BeginFetchAndCacheApply`/`HandleFetchedForApply`, ~1716/1723/1774/1785/1801). Its try/catch swallows the
null-factory NRE and logs a misleading "transient DB" warning on every deploy on a driver-only node. The
`_dbFactory is not null` guard fixes this.
- **`SpawnScriptedAlarmHost` (called unconditionally from PreStart ~524) constructs
`new EfAlarmConditionStateStore(_dbFactory, ...)` at ~587-588** — with a null factory every alarm
Load/Save NREs (swallowed → scripted-alarm state silently dead on driver-only nodes). **This is fixed by
Task 6** (which swaps in the LocalDb-backed store), NOT by a null guard — do NOT leave the Ef store
constructed with a null factory. If Task 6 lands after this task, add a temporary `_dbFactory is not null`
guard around the Ef-store construction so a DB-less node skips it cleanly until Task 6 wires the LocalDb
store; the two tasks together must leave a DB-less node with a WORKING (LocalDb) condition store, not a
skipped one.
**Step 1: Write failing tests** — construct a `DriverHostActor` with `dbFactory: null`,
`fetchAndCacheMode: true`, a fake fetcher + LocalDb cache (mirror `DriverHostActorFetchAndCacheTests`):
(a) a full dispatch → Applied ack, **no** NullReferenceException from a factory deref; (b) bootstrap