docs(localdb): phase-1 runbook + redundancy/config docs

New operations runbook (enable/disable, fail-closed ApiKey rule, stop/start-
together, tombstone-retention window, MaxBatchSize row-count-vs-4MB, never
sqlite3-a-live-WAL-DB cp-triplet recipe). Configuration.md gains a LocalDb
section; Redundancy.md gains a pair-local config cache section (what boot-from-
cache does and does not cover); CLAUDE.md gains the Phase 1 scope paragraph.
This commit is contained in:
Joseph Doherty
2026-07-20 22:06:58 -04:00
parent 7676ab93c4
commit c834d89ae7
4 changed files with 193 additions and 0 deletions
+29
View File
@@ -226,6 +226,35 @@ Net effect: each alarm transition appears **once** on `/alerts` and would histor
See [ScriptedAlarms.md](ScriptedAlarms.md) and [AlarmTracking.md](AlarmTracking.md) for the scripted-alarm engine internals.
## Pair-local config cache (LocalDb — Phase 1)
Independently of the ServiceLevel machinery above, every **driver-role** node keeps a consolidated
[`ZB.MOM.WW.LocalDb`](../CLAUDE.md) SQLite database that caches the **deployed-configuration
artifact** (chunked). Its job is a single failure mode redundancy does not otherwise cover: a driver
node restarting into a **central-SQL-Server outage** would come up with no configuration at all. With
the cache, it **boots from the last artifact it applied** instead, and logs a running-from-cache
signal.
- **What replicates.** The cache can *optionally* replicate to the node's redundant pair peer over
the LocalDb library's gRPC sync (HLC-stamped, last-writer-wins). Two tables replicate:
`deployment_artifacts` and `deployment_pointer`. Replication is **default-OFF and fail-closed**
it stays inert until `LocalDb:SyncListenPort` + a peer are configured, and a missing/mismatched
`LocalDb:Replication:ApiKey` refuses or silently halts sync. It is enabled per-pair as an opt-in.
- **The replicated-cache payoff.** In a pair with replication on, *either* node can be the one that
applied the latest deploy; the peer holds a byte-identical copy. So a node that restarts during a
central outage can boot the current config **even if it never applied that deploy itself** — its
peer did, and the row replicated.
- **What it does NOT cover.** The cache is a **boot fallback for central-SQL outages only**, not a
standby data path and not a replacement for central. A **new deployment still requires central
SQL**; the cache is read only when the central fetch fails at startup, and the node resumes
fresh-config behavior once central returns. It does not replicate live tag values, alarms, or
historian data — only the config artifact. It is orthogonal to the ServiceLevel/primary-gate
logic: a node running from cache still participates in redundancy normally.
Full detail: the enablement runbook at
[`docs/operations/2026-07-20-localdb-pair-replication.md`](operations/2026-07-20-localdb-pair-replication.md)
and the `LocalDb` section of [`docs/Configuration.md`](Configuration.md).
## Client-side failover
The OtOpcUa Client CLI at `src/Client/ZB.MOM.WW.OtOpcUa.Client.CLI` supports `-F` / `--failover-urls` for automatic client-side failover; for long-running subscriptions the CLI monitors session KeepAlive and reconnects to the next available server, recreating the subscription on the new endpoint. See [`Client.CLI.md`](Client.CLI.md).