chore(deps): bump Auth 0.2.1->0.3.0, LocalDb 0.2.1->0.3.4, MxGateway.Client/Contracts 0.2.0->0.2.1
v2-ci / build (push) Successful in 5m59s
v2-ci / unit-tests (push) Failing after 17m18s

Additive/wire-compatible releases across all three families; Directory.Packages.props
is the only pin surface (no csproj-level overrides, no lock files). Auth 0.3.0 adds
IApiKeyStoreMigrator and the optional Auth.ApiKeys.SqlServer package, neither needed
here. LocalDb 0.3.4's on-disk bookkeeping schema goes v2->v3 (upgrades in place on
open); 0.3.0 made the snapshot-resync flag per-table instead of per-database; 0.3.2
added validated Replication:KeepAlivePingDelay/KeepAlivePingTimeout config (defaults
60s/20s, left unset here) and a public LocalDbOplogGapException; 0.3.3 makes
RegisterReplicated throw LocalDbRegistrationException for a table that is the parent
of a row-mutating ON DELETE FK, which does not apply to this repo's four replicated
tables (no FKs). MxGateway.Client/Contracts 0.2.1 publishes the alarm snapshot_status
truncation frame and live alarm watch-list refresh; vendored the new nupkgs into
nuget-packages/ (the local-mxgw source MxGateway.* is exclusively package-source-mapped
to), matching the existing pattern from the 0.1.0->0.1.1 and 0.1.1->0.2.0 bumps.

Full solution builds clean (0 errors, 908 pre-existing analyzer warnings, unchanged
count). Full test suite: one failure, ClusterRoleInfoRoleLeaderCaseTests.
RoleLeaderChanged_for_driver_then_Driver_keeps_distinct_entries, reproduces
identically on the unbumped 0.2.1/0.2.1/0.2.0 tree under the same full-suite parallel
run (and passes standalone in isolation in 2s on the bumped tree) - a pre-existing
timing/parallelism flake, not a bump regression, so left as-is.

Updated CLAUDE.md and two docs (Configuration.md, operations/2026-07-20-localdb-pair-
replication.md) where they stated the old pin numbers and the now-superseded
per-database snapshot-resync behavior as current fact; dated historical records
(archreview snapshots, dated plan docs) were left untouched.

Claude-Session: https://claude.ai/code/session_01Wzg6NUCWHipSexLs2cgRFv
This commit is contained in:
Joseph Doherty
2026-09-03 11:23:21 -04:00
parent 2c792613bf
commit b8b4c18f54
6 changed files with 39 additions and 27 deletions
+19 -11
View File
@@ -721,13 +721,19 @@ same event accepted on both nodes — which happens in every boot window, since
docker-dev rig the site-a pair and site-b both run `AlarmHistorian__Enabled=true` against a
deliberately unresolvable gateway endpoint, so the buffer is always a live, non-draining queue.
**The library pin is `0.2.1`** (`Directory.Packages.props`, both `ZB.MOM.WW.LocalDb` and
`.Replication`), bumped from `0.1.3` on 2026-08-15. It was a **pure pin bump — no code change**:
`RegisterReplicated(string)` is unchanged, everything 0.2.x added is additive, the wire protocol is
untouched (0.1.x peers still sync), and the on-disk bookkeeping schema v1 → v2 upgrades in place on
open, so no rig or volume action was needed. **Its two new APIs — `DeregisterReplicated` and
`RegisterReplicated(table, baselineExistingRows:)` — are now both used** (2026-08-18); the bullets
below are the shape that landed, not the bump itself. Two things are worth knowing:
**The library pin is `0.3.4`** (`Directory.Packages.props`, both `ZB.MOM.WW.LocalDb` and
`.Replication`), bumped from `0.2.1` on 2026-09-03 (was itself bumped from `0.1.3` on 2026-08-15).
The 0.2.1→0.3.4 bump is wire-compatible with 0.2.x, and the on-disk bookkeeping schema v2 → v3
upgrades in place on open, so no rig or volume action was needed. `RegisterReplicated(string)` is
unchanged and everything 0.2.x/0.3.x added is additive, **except** that `RegisterReplicated` (0.3.3)
now throws `LocalDbRegistrationException` for a table that is the parent of a row-mutating ON
DELETE FK — none of this repo's four replicated tables have such an FK, so this did not fire.
0.3.0 made the snapshot-resync flag **per-table** (see the ⚠️ below, now corrected); 0.3.2 added
validated config `Replication:KeepAlivePingDelay`/`KeepAlivePingTimeout` (defaults 60s/20s, left
unset here) and a public `LocalDbOplogGapException`, neither yet wired to a call site. **Its two
new APIs — `DeregisterReplicated` and `RegisterReplicated(table, baselineExistingRows:)` — are now
both used** (2026-08-18); the bullets below are the shape that landed, not the bump itself. Two
things are worth knowing:
- **`MaxBatchSize` no longer means what the rig's `16` was chosen to mean.** 0.2.0 made batching
**byte-budgeted** — `LocalDb:Replication:MaxBatchBytes` (2 MB default, left unset here, sized
@@ -753,10 +759,12 @@ below are the shape that landed, not the bump itself. Two things are worth knowi
used to replicate only writes made after the restart. It seeds the ledger at the LWW floor
(HLC `0`, this node's id) and flags a resync — a baselined row loses to any genuine remote
write of the same key and wins only where the peer has no version at all. It is idempotent, so
it is free on every boot after the first. ⚠️ On the pinned **0.2.1** the snapshot flag is
per-**database**, not per-table, so baselining anything streams *every* registered table in
full, in both directions at once — trim `alarm_sf_events` before enabling replication on a node
that has been buffering alarm history for months, and expect one slow first sync.
it is free on every boot after the first. As of `0.3.0` (this repo pins `0.3.4`) the snapshot
flag is **per-table**, not per-database — baselining one table no longer streams every
registered table in both directions. (Prior to `0.3.0`, on the `0.2.1` pin this repo carried
until 2026-09-03, the flag was per-database and baselining anything streamed *every*
registered table in full; the old advice to trim `alarm_sf_events` before enabling replication
no longer applies at the current pin.)
- **Not configured ⇒ `DeregisterReplicated(table)` per table**, an idempotent boot-time
self-heal: it drops the capture triggers an earlier (unconditional) build left in the file and
prunes that table's oplog + row-version rows. Merely declining to register would leave every
+7 -7
View File
@@ -175,18 +175,18 @@
package floors the native SQLitePCLRaw.lib.e_sqlite3 at 2.1.12, so consumers inherit the
CVE-2025-6965-fixed native binary without needing the surgical pin below.
-->
<PackageVersion Include="ZB.MOM.WW.LocalDb" Version="0.2.1" />
<PackageVersion Include="ZB.MOM.WW.LocalDb.Replication" Version="0.2.1" />
<PackageVersion Include="ZB.MOM.WW.LocalDb" Version="0.3.4" />
<PackageVersion Include="ZB.MOM.WW.LocalDb.Replication" Version="0.3.4" />
<PackageVersion Include="ZB.MOM.WW.Health.Akka" Version="0.3.0" />
<PackageVersion Include="ZB.MOM.WW.Health.EntityFrameworkCore" Version="0.3.0" />
<PackageVersion Include="ZB.MOM.WW.Telemetry" Version="0.1.0" />
<PackageVersion Include="ZB.MOM.WW.Telemetry.Serilog" Version="0.1.0" />
<PackageVersion Include="ZB.MOM.WW.MxGateway.Client" Version="0.2.0" />
<PackageVersion Include="ZB.MOM.WW.MxGateway.Contracts" Version="0.2.0" />
<PackageVersion Include="ZB.MOM.WW.MxGateway.Client" Version="0.2.1" />
<PackageVersion Include="ZB.MOM.WW.MxGateway.Contracts" Version="0.2.1" />
<PackageVersion Include="ZB.MOM.WW.Configuration" Version="0.1.0" />
<PackageVersion Include="ZB.MOM.WW.Auth.Abstractions" Version="0.2.1" />
<PackageVersion Include="ZB.MOM.WW.Auth.Ldap" Version="0.2.1" />
<PackageVersion Include="ZB.MOM.WW.Auth.AspNetCore" Version="0.2.1" />
<PackageVersion Include="ZB.MOM.WW.Auth.Abstractions" Version="0.3.0" />
<PackageVersion Include="ZB.MOM.WW.Auth.Ldap" Version="0.3.0" />
<PackageVersion Include="ZB.MOM.WW.Auth.AspNetCore" Version="0.3.0" />
<PackageVersion Include="ZB.MOM.WW.Secrets" Version="0.6.2" />
<PackageVersion Include="ZB.MOM.WW.Secrets.Abstractions" Version="0.6.2" />
<PackageVersion Include="ZB.MOM.WW.Secrets.Ui" Version="0.6.2" />
+3 -3
View File
@@ -435,9 +435,9 @@ and syncs with nobody). A configured node registers all four tables with `baseli
turning replication on converges the rows **already in the file** and not merely subsequent writes; an
unconfigured node **deregisters** them at boot, dropping capture triggers an earlier build installed. ⚠️ The
sync handshake compares registered-table digests **fail-closed**, so flipping either key is a
both-nodes-together change: set it on both and restart both. On LocalDb 0.2.1 baselining flags a
**per-database** snapshot resync (every registered table, in full, both directions), so trim a long-running
`alarm_sf_events` buffer before enabling replication late.
both-nodes-together change: set it on both and restart both. As of LocalDb 0.3.0 (this repo pins
0.3.4) baselining flags a **per-table** snapshot resync — enabling replication on one table no
longer forces a full-database resync of every registered table in both directions.
Replication is **default-OFF** across the fleet; it is enabled per-pair as an opt-in. See
[`docs/operations/2026-07-20-localdb-pair-replication.md`](operations/2026-07-20-localdb-pair-replication.md)
@@ -77,12 +77,16 @@ Replication has two knobs, both under `LocalDb`:
| `LocalDb:Replication:MaxBatchSize` | secondary row cap **and** the DB read-page size | `16` for the artifact cache. **Since LocalDb 0.2.0 this no longer bounds the wire message** — `MaxBatchBytes` does — so it is not the byte proxy the note here used to describe. Keep it at `16` anyway: `OplogStore`/`SnapshotStreamer` materialise a whole read page in memory *before* the byte-budget split runs, and 16 × ≈171 KB artifact chunk rows ≈ 2.7 MB bounds that transient allocation. Raising it no longer risks tripping the gRPC cap, only the allocation. |
| `LocalDb:Replication:MaxBatchBytes` | primary cap on one outbound message (bytes) | Library default **2 MB**, sized under gRPC's 4 MB receive limit. Left unset on this rig. A single row over budget is sent alone rather than stalling the stream. |
> **Library version.** This repo pins **`ZB.MOM.WW.LocalDb` / `.Replication` 0.2.1**
> (`Directory.Packages.props`). The 0.1.3 → 0.2.1 move needed no config or code change here: the
> wire protocol is unchanged (0.1.x peers still sync), and the on-disk bookkeeping schema v1 → v2
> is upgraded **in place on open**, so an existing node's database file needs no operator action.
> Two behaviours changed that an operator should know: batching is now byte-budgeted (the two rows
> above), and **both of 0.2.x's lifecycle APIs are now used** (2026-08-18) — see the box below.
> **Library version.** This repo pins **`ZB.MOM.WW.LocalDb` / `.Replication` 0.3.4**
> (`Directory.Packages.props`; bumped from `0.2.1` on 2026-09-03, itself bumped from `0.1.3` on
> 2026-08-15). Every move in that chain needed no config or code change here: the wire protocol is
> unchanged end to end (0.1.x/0.2.x/0.3.x peers all still sync), and the on-disk bookkeeping schema
> upgrades in place on open (now v3) with no operator action on an existing node's database file.
> Behaviours worth knowing at the current pin: batching is byte-budgeted (the two rows above);
> **both of 0.2.x's lifecycle APIs are now used** (2026-08-18, see the box below); the
> snapshot-resync flag introduced by baselining is **per-table**, not per-database, since `0.3.0`;
> and `0.3.2` added validated `Replication:KeepAlivePingDelay`/`KeepAlivePingTimeout` config
> (defaults 60s/20s, left unset on this rig).
> **⚠️ Registration follows this config, and flipping it is a BOTH-NODES change.** Since
> 2026-08-18 `LocalDbSetup.OnReady` installs the change-capture triggers only when the node is