summaryrefslogtreecommitdiffstats
path: root/src/swarm/topology.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-10-24 04:23:38 +0200
committertv <tv@krebsco.de>2026-10-24 04:47:07 +0200
commit6fa188610ce0959e0b61ecaf63f5babf826d2071 (patch)
treea955457989abfe4832fe0213b5054d3b34c98ab1 /src/swarm/topology.rs
parentc2468964b11bd3606f03375c370fd181a1723113 (diff)
pull missing changes
Nodes push changes to their neighbours but don't relay them directly. In a partial mesh, nodes can learn about missing changes via keepalive messages and can pull them from their neighbours.
Diffstat (limited to 'src/swarm/topology.rs')
-rw-r--r--src/swarm/topology.rs17
1 files changed, 17 insertions, 0 deletions
diff --git a/src/swarm/topology.rs b/src/swarm/topology.rs
index b5880cf..dddf81b 100644
--- a/src/swarm/topology.rs
+++ b/src/swarm/topology.rs
@@ -33,6 +33,18 @@ pub(crate) struct NeighbourView {
k: usize,
unreachable: BTreeSet<String>,
neighbours: BTreeSet<String>,
+ /// Every reachable member is a neighbour.
+ full_mesh: bool,
+}
+
+/// Whether every reachable member is our neighbour (also while the view is unknown).
+pub(crate) fn is_full_mesh(state: &AppState) -> bool {
+ state
+ .neighbours
+ .read()
+ .unwrap_or_else(|poisoned| poisoned.into_inner())
+ .as_ref()
+ .is_none_or(|view| view.full_mesh)
}
/// Whether we initiate contact with `peer`: HELLOs, keepalives, dormancy checks, sync
@@ -113,10 +125,15 @@ pub(crate) async fn refresh(state: &AppState) -> Option<NeighbourChange> {
removed = change.removed.len(),
"Neighbours computed from the member list"
);
+ let reachable_others = current
+ .iter()
+ .filter(|m| m.as_str() != state.local_id() && !unreachable.contains(*m))
+ .count();
*state
.neighbours
.write()
.unwrap_or_else(|poisoned| poisoned.into_inner()) = Some(NeighbourView {
+ full_mesh: computed.len() >= reachable_others,
members: current,
k,
unreachable,