diff options
| author | tv <tv@krebsco.de> | 2026-10-26 19:29:59 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-26 19:29:59 +0100 |
| commit | 4bbadf6fdc4733b4c3c5eeb575508b2f9334ebdb (patch) | |
| tree | e79ad53ac99932c94b5bc581b382c919cfc9bb17 /src/swarm/relay.rs | |
| parent | 9a165fd06a1b52bb943a84f26adf8dec72056143 (diff) | |
keepalive sends head samples alongside digest
When there are more than 32 heads that can be send in a single keepalive
message, the digest is accompanied by 32 heads, a different window each
time, so after a few keepalives every head has been listed.
Diffstat (limited to 'src/swarm/relay.rs')
| -rw-r--r-- | src/swarm/relay.rs | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/src/swarm/relay.rs b/src/swarm/relay.rs index 7c56c90..087e028 100644 --- a/src/swarm/relay.rs +++ b/src/swarm/relay.rs @@ -128,20 +128,26 @@ pub(crate) async fn pull_if_behind( if ours == remote.heads { return false; } - let missing = match &remote.heads { - HeadsSummary::Heads(heads) => { - // AutoCommit's lookups take &mut self. - let mut replica = state.doc.write().await; - let missing = heads - .iter() - .any(|head| replica.doc.get_change_by_hash(head).is_none()); - if !missing { - return false; - } - Some(heads.clone()) - } - // Can't tell which heads are missing; the digest differs from ours, though. - HeadsSummary::Digest(_) => None, + // Those of the listed heads we lack. With a digest only a sample is listed; if we + // have all of it, a later keepalive lists others. + let missing: Vec<_> = { + // AutoCommit's lookups take &mut self. + let mut replica = state.doc.write().await; + remote + .heads + .listed() + .iter() + .filter(|head| replica.doc.get_change_by_hash(head).is_none()) + .copied() + .collect() + }; + if missing.is_empty() { + return false; + } + // All heads, when we know them; otherwise those we lack. + let theirs = match remote.heads.heads() { + Some(heads) => heads.to_vec(), + None => missing, }; let Some(peer_state) = state.get_peer_state(peer).await else { @@ -166,13 +172,8 @@ pub(crate) async fn pull_if_behind( pulling.waiting.remove(peer); } - match missing { - // Automerge asks for whatever these heads need that we don't have. - Some(heads) => peer_state.lock().await.sync.pull_from(heads), - // A fresh session's opening carries our heads and bloom filter; the answer - // brings what we lack. - None => peer_state.lock().await.reset_sync(), - } + // Automerge asks for whatever these heads need that we don't have. + peer_state.lock().await.sync.pull_from(theirs); debug!(peer = %peer, "Neighbour has changes we lack; pulling"); let _ = state .sync_events |
