diff options
| author | tv <tv@krebsco.de> | 2026-11-05 01:23:40 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-05 01:23:40 +0100 |
| commit | 889e23ee1eb8a209efe7c1eae86aa39091560149 (patch) | |
| tree | 8da04d6d62f9a1647f90b6ea459eba62b91f5a12 /src/swarm/tree.rs | |
| parent | 0d16147e95211b0829fddaefb0d014fe0c48dbc8 (diff) | |
covered neighbours have it
Diffstat (limited to 'src/swarm/tree.rs')
| -rw-r--r-- | src/swarm/tree.rs | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/src/swarm/tree.rs b/src/swarm/tree.rs index 015d62c..20df2ec 100644 --- a/src/swarm/tree.rs +++ b/src/swarm/tree.rs @@ -284,6 +284,9 @@ pub(crate) struct Plan { /// Our neighbours that no member they reach comes before (the tree reaches them only /// by announcement), and those not in the member list's graph (whom no tree has). pub(crate) uncovered: Vec<String>, + /// Our neighbours that get the writer's changes from another parent, and the writer + /// itself: they have them, or will, without us (`forward`). + pub(crate) covered: Vec<String>, } /// Our part in `writer`'s tree (`children`, `Plan`); None while the member list isn't @@ -305,11 +308,13 @@ pub(crate) async fn plan(state: &AppState, writer: u64) -> Option<Plan> { let mut children = Vec::new(); let mut alone = Vec::new(); let mut uncovered = Vec::new(); + let mut covered = Vec::new(); for member in graph.get(me).into_iter().flatten() { let Some(its_rank) = rank(&graph, &distance, &reached, member) else { continue; }; if distance[member.as_str()] == 0 { + covered.push(member.clone()); continue; } match parent(&graph, &distance, &reached, member) { @@ -325,6 +330,8 @@ pub(crate) async fn plan(state: &AppState, writer: u64) -> Option<Plan> { } children.push(member.clone()); } + Some(parent) if parent != me => covered.push(member.clone()), + // Ours by the graph, but we don't reach it, or it comes before us. Some(_) => {} } } @@ -341,14 +348,34 @@ pub(crate) async fn plan(state: &AppState, writer: u64) -> Option<Plan> { children, alone, uncovered, + covered, }) } -/// We applied a change of `writer`'s that `from` passed on: to our children in its -/// tree (but `from`), a sync message each, saying whose. Returns our part in the tree -/// (`Plan`), None if we have none (announcements then do it all). -pub(crate) async fn forward(state: &AppState, writer: u64, from: &str) -> Option<Plan> { +/// We applied `changes` of `writer`'s that `from` passed on (none if we had them +/// already): to our children in its tree (but `from`), a sync message each, saying +/// whose. Returns our part in the tree (`Plan`), None if we have none (announcements +/// then do it all). +/// +/// Our neighbours that get them from another parent (`Plan::covered`) count as having +/// them (`SyncSession::known_to_peer`): else, with writers in turn, each change coming +/// along another tree, the next message we pass on to one would carry all we got since +/// our last to it, mostly what its other parents brought it. Should one lack them after +/// all, it asks, and gets them (`resend_if_needed`). +pub(crate) async fn forward( + state: &AppState, + writer: u64, + from: &str, + changes: &[crate::document::ChangeHash], +) -> Option<Plan> { let mut plan = plan(state, writer).await?; + if !changes.is_empty() { + for neighbour in &plan.covered { + if let Some(peer_state) = state.get_peer_state(neighbour).await { + peer_state.lock().await.sync.known_to_peer(changes); + } + } + } plan.children.retain(|child| child != from); let children = &plan.children; for child in children { |
