aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm/reach.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-06 05:29:17 +0100
committertv <tv@krebsco.de>2026-11-06 05:29:17 +0100
commit7f2d5be7a5cd4204fe0ec933fe4d99134607e1b3 (patch)
tree49bc403457c64113890e4ca2c16e307d7d8adbc1 /src/swarm/reach.rs
parent6f51f8ee9624ecb15d9c9ad6656e69056e245e7b (diff)
working links recorded
Diffstat (limited to 'src/swarm/reach.rs')
-rw-r--r--src/swarm/reach.rs42
1 files changed, 27 insertions, 15 deletions
diff --git a/src/swarm/reach.rs b/src/swarm/reach.rs
index d4949ef..760bcb5 100644
--- a/src/swarm/reach.rs
+++ b/src/swarm/reach.rs
@@ -15,8 +15,9 @@
//! reach, as of their latest STATUS, for as long as the session lasts (a
//! neighbour that goes dormant, or starts anew, says it again). Not for a set time:
//! while a pair exchanges changes it sends no keepalives, and so no STATUS, for as
-//! long as the writes go on. Nothing goes into the document, and nobody knows more than
-//! two hops out.
+//! long as the writes go on. Nothing of it goes into the document (but where a link
+//! stays down for a while: `swarm::working_links`), and nobody knows more than two hops
+//! out.
//!
//! What it is for: passing changes on around links that don't work, and to exactly the
//! members the sender doesn't reach; a member a neighbour reaches is one worth trying,
@@ -25,7 +26,7 @@
//! every neighbour would be one (13.7 of 13.7 at 250 members and more), saving next to
//! nothing but in a full mesh.
-use std::collections::HashMap;
+use std::collections::{BTreeSet, HashMap};
use tokio::time::Instant;
use tracing::debug;
@@ -77,18 +78,11 @@ pub(crate) struct Reach {
/// told before (`before`, by pair key: `rtt::bucket`).
async fn measure(state: &AppState, before: &HashMap<u64, u8>) -> (Vec<u64>, Vec<u8>) {
let now = Instant::now();
- let mut reached = Vec::new();
- for (peer, peer_state) in state.peers_snapshot().await {
- let peer_state = peer_state.lock().await;
- if peer_state.hello_state == HelloState::Established
- && !peer_state.liveness.is_dormant()
- && !peer_state.is_unreachable()
- && !peer_state.answer_overdue(now)
- && matches!(peer_state.standing, Standing::Member { .. })
- {
- reached.push((topology::pair_key(&peer), peer));
- }
- }
+ let mut reached: Vec<(u64, String)> = reached_members(state, now)
+ .await
+ .into_iter()
+ .map(|peer| (topology::pair_key(&peer), peer))
+ .collect();
reached.sort_unstable();
let rtts = state.lock_rtt();
let round_trips = reached
@@ -104,6 +98,24 @@ async fn measure(state: &AppState, before: &HashMap<u64, u8>) -> (Vec<u64>, Vec<
)
}
+/// The members we reach now: those with an active session (handshake done, neither
+/// dormant nor unreachable) that answer.
+pub(crate) async fn reached_members(state: &AppState, now: Instant) -> BTreeSet<String> {
+ let mut reached = BTreeSet::new();
+ for (peer, peer_state) in state.peers_snapshot().await {
+ let peer_state = peer_state.lock().await;
+ if peer_state.hello_state == HelloState::Established
+ && !peer_state.liveness.is_dormant()
+ && !peer_state.is_unreachable()
+ && !peer_state.answer_overdue(now)
+ && matches!(peer_state.standing, Standing::Member { .. })
+ {
+ reached.insert(peer);
+ }
+ }
+ reached
+}
+
/// Whom we reach, as we tell it (`Status::reaches`); empty until first measured.
pub(crate) fn published(state: &AppState) -> Vec<u64> {
published_with_round_trips(state).0