From ea53d62019b3905f6a1a8daeca06e5aeb5c3b6ad Mon Sep 17 00:00:00 2001 From: tv Date: Fri, 23 Oct 2026 20:41:50 +0200 Subject: introduce announce opening variant This prevents a fall back to the 3 s grace period if a reset happens between the epoch switch and our opening went out. --- src/state.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/state.rs b/src/state.rs index 5e9b03b..3ee9c6c 100644 --- a/src/state.rs +++ b/src/state.rs @@ -153,11 +153,14 @@ pub(crate) struct SyncSession { /// the side that leads the pair opens. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub(crate) enum Opening { - /// We open: we lead the pair, or we just switched epochs and the peer, already on our - /// new epoch, still has our old one on record. It won't sync with us until a message - /// tells it otherwise, and our opening does (no epoch announcement PING needed). A - /// reset before the opening goes out falls back to the grace period below. + /// We open: we lead the pair. Ours, + /// We open, leader or not: we just switched epochs, and the peer, already on our new + /// epoch, still has our old one on record. It won't sync with us until a message + /// tells it otherwise, and our opening does (no epoch announcement PING needed). + /// Survives resets until the peer has answered, since only then do we know it + /// learned our epoch. + Announce, /// The peer opens. If nothing came by `until`, we open anyway: the peer may not have /// reset, or its opening got lost. Theirs { until: Instant }, @@ -252,7 +255,7 @@ impl SyncSession { return None; } match self.opening { - Opening::Ours => None, + Opening::Ours | Opening::Announce => None, Opening::Theirs { until } => until .checked_duration_since(now) .filter(|wait| !wait.is_zero()), @@ -325,7 +328,12 @@ impl PeerState { /// Start Automerge sync with this peer from scratch. Any envelope generated against /// the old state is discarded; a stale RetryDelivery event is then a no-op. pub(crate) fn reset_sync(&mut self, cause: SessionCause) { + let announce = + self.sync.opening == Opening::Announce && self.sync.state.their_heads.is_none(); self.sync = SyncSession::new(self.leads, cause); + if announce { + self.sync.opening = Opening::Announce; + } } /// An overdue sync answer from an established, active peer (see @@ -763,7 +771,7 @@ impl AppState { && matches!(peer_state.standing, Standing::Member { .. }) && peer_state.epoch == Some(local); if syncs_with_us { - peer_state.sync.opening = Opening::Ours; + peer_state.sync.opening = Opening::Announce; } else { announce.push(id); } -- cgit v1.3.1