ops(docker)+test(host)+docs: close register rows 104 + 105 — offline VACUUM recipe applied to the rig; build-time pin that no replicated table is a cascading-FK parent; record row 106 (LocalDb as_of_seq=0 full-snapshot loop)
Row 104: docker/vacuum-site-localdb.sh stops both nodes of a pair together, sets auto_vacuum=INCREMENTAL + VACUUM on each node volume with integrity_check before/after, then starts both (DRY_RUN=1 reports). Run on all three rig pairs: six files 0 -> 2, ok, ~11% smaller; site-a replication reconnected with backlog 0 and no watermark change — VACUUM is replication-invisible (ledger keys by declared PK, oplog seq is INTEGER PRIMARY KEY AUTOINCREMENT). Topology guide gains the recipe. Row 105: SiteLocalDbReplicatedTableFkGuardTests builds the real site schema via OnReady (unreplicated config so 0.3.3's own guard cannot mask the culprit) and asserts every SiteLocalDbSetup.ReplicatedTables entry (now internal) exists and has no inbound CASCADE/SET NULL/SET DEFAULT foreign key, with a negative control. The constraint is enforced at build instead of at the first replicated boot. Row 106 (found during 104's live verification, NOT caused by it — the identical 127k-row full snapshot also landed at the earlier deploy restart): SnapshotStreamer.SendAsync stamps as_of_seq = MAX(seq), which is 0 once a converged sender's oplog is ack-pruned to empty; a zero-watermark receiver (rebuilt node) is never lifted, so the empty-oplog horizon rule re-streams a full snapshot on every reconnect. Sender-side one-line fix for LocalDb 0.3.4: as_of_seq = max(MAX(seq), last_acked_seq).
This commit is contained in:
@@ -357,6 +357,33 @@ a rejoin is safe and self-correcting (verified live: a node stopped and restarte
|
||||
with both nodes byte-identical and zero duplicates). Beyond it, rebuild the returning node's
|
||||
database from its peer rather than letting it rejoin.
|
||||
|
||||
### Site LocalDb files created before 2026-08-20 need a one-off offline VACUUM
|
||||
|
||||
SQLite honours `PRAGMA auto_vacuum` only on a table-less database, and until arch-review
|
||||
2026-08-19 P4-6 the pragma ran AFTER LocalDb had created its bookkeeping tables — so every site
|
||||
file created before that fix is `auto_vacuum=NONE`, and the event-log cap trim's
|
||||
`PRAGMA incremental_vacuum` is a silent no-op on it: freed `site_events` pages are reused, but the
|
||||
file never shrinks (deferred-work register row 104). Fresh files are now created
|
||||
`auto_vacuum=INCREMENTAL`; existing files need a **full `VACUUM` with the pragma set**, which
|
||||
rewrites the file and is therefore deliberately NOT done at boot (minutes of exclusive lock on a
|
||||
~1 GB file).
|
||||
|
||||
Run it in a maintenance window with **both nodes of the pair stopped** (the rule above):
|
||||
|
||||
```bash
|
||||
DRY_RUN=1 bash docker/vacuum-site-localdb.sh --all # report: 0 = NONE, 2 = INCREMENTAL
|
||||
bash docker/vacuum-site-localdb.sh a # one pair: stop both → VACUUM both → start both
|
||||
```
|
||||
|
||||
The script integrity-checks each file before and after and leaves the pair stopped if the
|
||||
post-check fails. It is safe for a replicated pair: `VACUUM` fires no triggers and changes no
|
||||
row content, the LWW ledger keys by declared primary key, and the oplog `seq` watermark is an
|
||||
`INTEGER PRIMARY KEY AUTOINCREMENT` — all preserved by `VACUUM`. Verified on the docker rig
|
||||
2026-08-20 on all three pairs: site-a (replicated) came back `LocalDbReplicationConnected=true`
|
||||
with backlog 0 and no schema or watermark change. For a non-docker deployment the recipe is the
|
||||
same three statements against the stopped node's `LocalDb:Path` file:
|
||||
`PRAGMA auto_vacuum = INCREMENTAL; VACUUM; PRAGMA integrity_check;`.
|
||||
|
||||
### Docker-rig data files on macOS/OrbStack — a virtiofs corruption + availability hazard
|
||||
|
||||
**Status: MITIGATED 2026-08-18 (register row 79) — the rigs' data dirs moved to named docker
|
||||
|
||||
Reference in New Issue
Block a user