diff options
Diffstat (limited to 'src/swarm/peer')
| -rw-r--r-- | src/swarm/peer/inbound.rs | 24 | ||||
| -rw-r--r-- | src/swarm/peer/keepalive.rs | 4 |
2 files changed, 23 insertions, 5 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 diff --git a/src/swarm/peer/keepalive.rs b/src/swarm/peer/keepalive.rs index 8362d73..f4e961f 100644 --- a/src/swarm/peer/keepalive.rs +++ b/src/swarm/peer/keepalive.rs @@ -33,8 +33,8 @@ pub(crate) async fn send_status(state: &AppState, peer: &str) -> Result<()> { } /// Sends `peer` a STATUS announcing our new heads (`swarm::relay`): no keepalive, so it -/// leaves the keepalives' schedule as it is, and it is answered only if the peer's heads -/// differ (`Status::announcing`). Whom we reach only `with_reaches` (`swarm::reach`): +/// leaves the keepalives' schedule as it is, and it is answered only if the peer lacks +/// some of our heads (`Status::announcing`). Whom we reach only `with_reaches` (`swarm::reach`): /// announcements of heads go often. pub(crate) async fn announce_heads(state: &AppState, peer: &str, with_reaches: bool) -> Result<()> { let local = local_status(state, peer).await; |
