aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm
diff options
context:
space:
mode:
Diffstat (limited to 'src/swarm')
-rw-r--r--src/swarm/peer/keepalive.rs4
-rw-r--r--src/swarm/relay.rs30
2 files changed, 20 insertions, 14 deletions
diff --git a/src/swarm/peer/keepalive.rs b/src/swarm/peer/keepalive.rs
index 3b78b85..d698585 100644
--- a/src/swarm/peer/keepalive.rs
+++ b/src/swarm/peer/keepalive.rs
@@ -250,12 +250,14 @@ pub(super) async fn note_status(state: &AppState, peer: &str, remote: &transport
),
}
}
+ // One grace wait per peer: a STATUS meanwhile only becomes the one it ends with.
+ let waiting = peer_state.pull_pending.replace(remote.clone()).is_some();
drop(peer_state);
if left {
info!(peer = %peer, "Peer said farewell; dormant until it is heard from again");
}
// Off the consumer: telling which heads we lack takes the document's lock.
- {
+ if !waiting {
let (state, peer, remote) = (state.clone(), peer.to_owned(), remote.clone());
tokio::spawn(async move {
crate::swarm::relay::pull_after_grace(&state, &peer, &remote).await;
diff --git a/src/swarm/relay.rs b/src/swarm/relay.rs
index 31df0d3..0f8a697 100644
--- a/src/swarm/relay.rs
+++ b/src/swarm/relay.rs
@@ -325,21 +325,25 @@ pub(crate) async fn lacks(state: &AppState, heads: &HeadsSummary) -> bool {
/// most; at once if we know none). While writes go on, the newest of them are usually
/// on their way to us along their writers' trees, as fast as the STATUS: they come
/// meanwhile, and pulling them would only fetch them twice. What is still missing then
-/// was missed.
+/// was missed. One wait per peer: a STATUS that comes meanwhile is the one judged at the
+/// end (`PeerState::pull_pending`).
pub(crate) async fn pull_after_grace(state: &AppState, peer: &str, remote: &transport::Status) {
- if HeadsSummary::of(state.stamp.borrow().heads.to_vec()) == remote.heads {
- return;
- }
- let grace = state
- .lock_rtt()
- .effective(peer, Instant::now(), state.timing.rtt_fresh_for())
- .map(|rtt| rtt.min(PULL_GRACE_MAX));
- if let Some(grace) = grace
- && lacks(state, &remote.heads).await
- {
- tokio::time::sleep(grace).await;
+ if HeadsSummary::of(state.stamp.borrow().heads.to_vec()) != remote.heads {
+ let grace = state
+ .lock_rtt()
+ .effective(peer, Instant::now(), state.timing.rtt_fresh_for())
+ .map(|rtt| rtt.min(PULL_GRACE_MAX));
+ if let Some(grace) = grace
+ && lacks(state, &remote.heads).await
+ {
+ tokio::time::sleep(grace).await;
+ }
}
- pull_if_behind(state, peer, remote).await;
+ let latest = match state.get_peer_state(peer).await {
+ Some(peer_state) => peer_state.lock().await.pull_pending.take(),
+ None => None,
+ };
+ pull_if_behind(state, peer, latest.as_ref().unwrap_or(remote)).await;
}
/// If `peer` has heads we lack (as its STATUS `remote` says), pull them (one peer at a