diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/state.rs | 6 | ||||
| -rw-r--r-- | src/swarm/peer.rs | 21 | ||||
| -rw-r--r-- | src/swarm/sync.rs | 16 |
3 files changed, 34 insertions, 9 deletions
diff --git a/src/state.rs b/src/state.rs index 71f7961..50e651e 100644 --- a/src/state.rs +++ b/src/state.rs @@ -178,6 +178,12 @@ impl PeerState { } } + /// Keepalives show both documents are the same: stop waiting for an answer. + pub(crate) fn sync_in_step(&mut self) { + self.sync_reply = None; + self.sync_reply_timeout = SYNC_REPLY_TIMEOUT; + } + /// The peer answered. pub(crate) fn sync_reply_received(&mut self) { self.sync_reply = None; diff --git a/src/swarm/peer.rs b/src/swarm/peer.rs index d801b0f..bad8e24 100644 --- a/src/swarm/peer.rs +++ b/src/swarm/peer.rs @@ -133,12 +133,21 @@ async fn heal_if_diverged( return; }; - let heal = peer_state_mutex.lock().await.needs_heal( - &local.heads_digest, - &remote.heads_digest, - &state.timing, - Instant::now(), - ); + let heal = { + let mut peer_state = peer_state_mutex.lock().await; + if local.heads_digest == remote.heads_digest { + // Same document: whatever answer we were waiting for, there is nothing left + // to send. (Automerge answers only when it has something to say, so a sync + // message to a peer that already has everything gets no reply at all.) + peer_state.sync_in_step(); + } + peer_state.needs_heal( + &local.heads_digest, + &remote.heads_digest, + &state.timing, + Instant::now(), + ) + }; if heal { warn!(peer = %peer, "Documents differ and sync is idle; re-handshaking to restart sync"); diff --git a/src/swarm/sync.rs b/src/swarm/sync.rs index 0c7148e..e294201 100644 --- a/src/swarm/sync.rs +++ b/src/swarm/sync.rs @@ -110,9 +110,19 @@ async fn deliver_sync_to_peer(state: &AppState, peer: &str, retry_delivery: bool peer_state.needs_generate = false; let epoch = replica.epoch; let sent_before = peer_state.sync_state.sent_hashes.clone(); - let sync_doc = replica.doc.sync(); - let message = sync_doc.generate_sync_message(&mut peer_state.sync_state); - if message.is_some() { + let message = { + let sync_doc = replica.doc.sync(); + sync_doc.generate_sync_message(&mut peer_state.sync_state) + }; + // A peer whose heads are ours already has everything; Automerge + // answers only when it has something to say, so it will stay + // silent. Waiting for an answer would only end in a pointless + // resend. + let in_step = peer_state.sync_state.their_heads.as_ref() + == Some(&replica.doc.get_heads()); + if in_step { + peer_state.sync_in_step(); + } else if message.is_some() { let sent = peer_state .sync_state .sent_hashes |
