diff options
| author | tv <tv@krebsco.de> | 2026-10-26 18:51:01 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-26 18:51:01 +0100 |
| commit | 8d70536fd267e7ee730c390b6b47c03ddbef7df9 (patch) | |
| tree | fbbd93242874765903ce7113fe78e3159f304a29 /src/swarm/peer/keepalive.rs | |
| parent | 8b7bf576d2b3ceb3e5b6cdae7a00989bebb3b4c4 (diff) | |
read stamps sync and lock free
Diffstat (limited to 'src/swarm/peer/keepalive.rs')
| -rw-r--r-- | src/swarm/peer/keepalive.rs | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/src/swarm/peer/keepalive.rs b/src/swarm/peer/keepalive.rs index 4fcad7e..4ce326e 100644 --- a/src/swarm/peer/keepalive.rs +++ b/src/swarm/peer/keepalive.rs @@ -25,14 +25,14 @@ pub(crate) async fn send_ping(state: &AppState, peer: &str) -> Result<()> { /// Our keepalive for `peer`. pub(crate) async fn local_keepalive(state: &AppState, peer: &str) -> transport::Keepalive { - // Heads and epoch come from the same locked replica, so they always match. The heads - // are cached (`Replica`), so the read lock is enough. + // Heads and epoch are published together (`Replica::stamps`), so they always match, + // and reading them doesn't wait for a sync message being applied. let (heads, epoch, epoch_seq) = { - let replica = state.doc.read().await; + let stamp = state.stamp.borrow(); ( - transport::HeadsSummary::of(replica.heads().to_vec()), - replica.epoch, - replica.epoch_seq, + transport::HeadsSummary::of(stamp.heads.to_vec()), + stamp.epoch, + stamp.epoch_seq, ) }; let syncs_with_you = match state.get_peer_state(peer).await { @@ -62,7 +62,13 @@ pub(super) async fn note_keepalive(state: &AppState, peer: &str, remote: &transp peer_state.syncs_with_us = Some(remote.syncs_with_you); peer_state.reported_heads = remote.heads.heads().map(<[_]>::len); drop(peer_state); - crate::swarm::relay::pull_if_behind(state, peer, remote).await; + // Off the consumer: telling which heads we lack takes the document's lock. + { + let (state, peer, remote) = (state.clone(), peer.to_owned(), remote.clone()); + tokio::spawn(async move { + crate::swarm::relay::pull_if_behind(&state, &peer, &remote).await + }); + } if became_ready { // We may have left the opening to it while it wasn't ready, and nothing else // would make us look again. |
