From cad3bcb6bf7582a6cba5fe1f3ef3873e1a225b27 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Tue, 21 Jul 2026 01:17:32 -0400 Subject: [PATCH] fix(localdb): snapshot a wiped peer whose deltas were already acked and pruned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A converged pair prunes its oplog on ack, so "no oplog rows at all" is the steady state of a healthy pair — not an anomaly. ComputeSnapshotRequiredAsync measured the peer's gap against the oldest surviving oplog row and treated an empty oplog as "no gap possible", which made that steady state the one state from which a wiped peer could never be healed: it reconnected with an empty database and a zero watermark, was told it needed no snapshot, and stayed empty indefinitely. With an empty oplog the oldest seq we could still stream is one past last_acked_seq — ack-pruning is the only thing that empties the oplog without also flagging needs_snapshot, and it deletes exactly seq <= last_acked_seq. Measuring the gap against that heals the wiped peer and leaves every other case identical: a converged peer's watermark equals last_acked_seq (no snapshot), and a pair that has never written anything has both at zero. Found by the OtOpcUa LocalDb Phase 1 live gate (check 4), which recorded it as a documented limitation. Covered by a test that reproduces the live-gate scenario through the real session stack: RED before this fix (the wiped side never converges, 15 s timeout), green after. 148/148 pass. Version 0.1.2. Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW --- ZB.MOM.WW.LocalDb/Directory.Build.props | 2 +- ZB.MOM.WW.LocalDb/README.md | 11 ++++- .../Internal/SyncSession.cs | 17 ++++++-- .../SnapshotResyncTests.cs | 42 +++++++++++++++++++ 4 files changed, 66 insertions(+), 6 deletions(-) diff --git a/ZB.MOM.WW.LocalDb/Directory.Build.props b/ZB.MOM.WW.LocalDb/Directory.Build.props index 9a1a7b9..9fdd454 100644 --- a/ZB.MOM.WW.LocalDb/Directory.Build.props +++ b/ZB.MOM.WW.LocalDb/Directory.Build.props @@ -5,7 +5,7 @@ enable enable latest - 0.1.1 + 0.1.2 true true