feat(localdb): oplog store (batch read, ack watermark, pruning caps, tombstone retention)

Claude-Session: https://claude.ai/code/session_01BL2Vu1ESDQ9SCN4gVKkdts
This commit is contained in:
Joseph Doherty
2026-07-17 21:45:20 -04:00
parent c061ba733f
commit 529585163c
3 changed files with 344 additions and 0 deletions
@@ -0,0 +1,37 @@
namespace ZB.MOM.WW.LocalDb.Replication;
/// <summary>
/// Configuration for the bidirectional 2-node replication engine. All durations are wall-clock UTC.
/// </summary>
public sealed class ReplicationOptions
{
/// <summary>gRPC address of the peer to dial. Required for the initiator role (validated in the sync host).</summary>
public string PeerAddress { get; set; } = "";
/// <summary>API key presented to / expected from the peer; null disables key auth.</summary>
public string? ApiKey { get; set; }
/// <summary>How often the change pump flushes pending oplog deltas to the peer.</summary>
public TimeSpan FlushInterval { get; set; } = TimeSpan.FromMilliseconds(250);
/// <summary>Maximum oplog entries sent per outbound batch.</summary>
public int MaxBatchSize { get; set; } = 500;
/// <summary>Backlog ceiling: exceeding it flags a snapshot resync and prunes the oldest oplog rows.</summary>
public long MaxOplogRows { get; set; } = 1_000_000;
/// <summary>Age ceiling: an unpruned oplog entry older than this flags a snapshot resync.</summary>
public TimeSpan MaxOplogAge { get; set; } = TimeSpan.FromDays(7);
/// <summary>How long deleted-row tombstones are retained before pruning.</summary>
public TimeSpan TombstoneRetention { get; set; } = TimeSpan.FromDays(7);
/// <summary>Upper bound on the exponential reconnect backoff.</summary>
public TimeSpan ReconnectBackoffMax { get; set; } = TimeSpan.FromSeconds(60);
/// <summary>Maximum tolerated HLC drift where a peer's clock runs ahead of ours.</summary>
public TimeSpan MaxHlcDriftAhead { get; set; } = TimeSpan.FromMinutes(5);
/// <summary>When true, drift beyond <see cref="MaxHlcDriftAhead"/> rejects the batch instead of clamping.</summary>
public bool FailClosedOnDrift { get; set; }
}