From 944bd3a9da9c14153247b483ba2cfe1457fc84d2 Mon Sep 17 00:00:00 2001 From: tv Date: Sun, 25 Oct 2026 20:33:40 +0100 Subject: late messages don't flip peer's epoch back --- src/state.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src/state.rs') diff --git a/src/state.rs b/src/state.rs index ce47673..d14c1ea 100644 --- a/src/state.rs +++ b/src/state.rs @@ -127,8 +127,14 @@ pub(crate) struct PeerState { /// from it in between (None while they match). pub(crate) diverged_since: Option, - /// Epoch the peer advertised in its most recent message. + /// Epoch the peer advertised in its most recent message (late ones aside: see + /// `epoch_seq`). pub(crate) epoch: Option, + /// The peer's `epoch_seq` with `epoch`: how many times it changed epoch in its run. + /// An epoch with a lower one is older than what we have, delivered late. + pub(crate) epoch_seq: Option, + /// The peer's run, from its HELLO or HELLO_REPLY: a new one starts `epoch_seq` over. + pub(crate) run_id: Option, /// Whether the peer was ready according to its most recent sync message or keepalive. pub(crate) reports_ready: Option, @@ -330,6 +336,8 @@ impl PeerState { last_resync_at: None, diverged_since: None, epoch: None, + epoch_seq: None, + run_id: None, reports_ready: None, syncs_with_us: None, reported_heads: None, @@ -676,6 +684,12 @@ impl AppState { *self.epoch_tx.borrow() } + /// The local epoch and `Replica::epoch_seq`, read together. + pub(crate) async fn epoch_stamp(&self) -> (Epoch, u32) { + let replica = self.doc.read().await; + (replica.epoch, replica.epoch_seq) + } + pub(crate) async fn is_ready(&self) -> bool { matches!(*self.lifecycle.read().await, NodeLifecycle::Ready { .. }) } @@ -1213,6 +1227,7 @@ impl Host for AppState { let new_doc = f(&mut replica.doc)?; let old_doc = std::mem::replace(&mut replica.doc, new_doc); replica.epoch = epoch; + replica.epoch_seq += 1; replica.refresh_heads(); // Updated under the same lock, so the cached epoch never disagrees // with the document for anyone holding the lock. -- cgit v1.3.1