diff options
Diffstat (limited to 'src/swarm/peer/inbound.rs')
| -rw-r--r-- | src/swarm/peer/inbound.rs | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/src/swarm/peer/inbound.rs b/src/swarm/peer/inbound.rs index 1454c3e..28066cb 100644 --- a/src/swarm/peer/inbound.rs +++ b/src/swarm/peer/inbound.rs @@ -143,13 +143,31 @@ pub(crate) async fn handle_message( crate::swarm::blob::handle(state, &peer, blob).await; } transport::ParsedMessage::Status(remote) => { - // An announcement is no keepalive; it is answered only if our heads differ, - // so the announcer learns what we have that it lacks. + // An announcement is no keepalive; it is answered only if we lack some of the + // heads it announced (`relay::lacks`), so the announcer learns what we have + // that it lacks while we pull. Having all of them, we are as far or further, + // and what we have further we announced ourselves; differing heads alone are + // no reason, as changes on their way to us make them differ while writes go on. if !remote.announcing { status_received(state, &peer).await; } let local = on_status(state, &peer, &remote, reactivated).await; - if remote.announcing && local.heads == remote.heads { + if remote.announcing { + if local.heads != remote.heads { + // Off the consumer: telling which heads we lack takes the document's + // lock. + let (state, peer) = (state.clone(), peer.clone()); + tokio::spawn(async move { + if crate::swarm::relay::lacks(&state, &remote.heads).await + && let Err(error) = state + .transport + .send_message(&peer, &ParsedMessage::StatusReply(local)) + .await + { + debug!(peer = %peer, error = %format!("{error:#}"), "STATUS_REPLY failed"); + } + }); + } return Ok(()); } if let Err(error) = state |
