aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-10-31 06:19:34 +0100
committertv <tv@krebsco.de>2026-10-31 06:19:34 +0100
commit7997793798b8364212fd0f009a68394d61a83e47 (patch)
tree13621c9dee8d1faf35a3524992c413f10aad9344 /src/swarm
parent7a0d6c0d644cb7328cdae24aebc08375c3ba6d94 (diff)
dashboard: try to get links dormant immediately
Diffstat (limited to 'src/swarm')
-rw-r--r--src/swarm/links.rs15
-rw-r--r--src/swarm/peer/inbound.rs18
2 files changed, 21 insertions, 12 deletions
diff --git a/src/swarm/links.rs b/src/swarm/links.rs
index fa05e72..7585d3b 100644
--- a/src/swarm/links.rs
+++ b/src/swarm/links.rs
@@ -1,8 +1,8 @@
//! How members are linked, for a map of the swarm (the dashboard, `api::dashboard`): a
//! node asks a member with LINKS, and the member answers with a LINKS_REPLY listing its
-//! neighbours, each with the transport its messages go over, whether only through a
-//! relay, the round trip and whether the neighbour is dormant: as the member measures
-//! them, which no other node can.
+//! neighbours and the peers it holds dormant (`own_links`), each with the transport its
+//! messages go over, whether only through a relay, the round trip and whether it is
+//! dormant: as the member measures them, which no other node can.
//!
//! Every node answers, whatever its build: one with a dashboard asks any member, which
//! may have none. Only members (in the member list) are answered, as the links name
@@ -101,14 +101,17 @@ impl Links {
}
}
-/// This node's links: its neighbours, as it measures them.
+/// This node's links: its neighbours, and the peers it holds dormant, as it measures
+/// them. A neighbour that goes dormant is one no more (it is unreachable now), but its
+/// link stays listed, dormant, until it is heard from again: left out, the link would
+/// show only as that peer last reported it, from before.
pub(crate) async fn own_links(state: &AppState) -> Vec<Link> {
let mut links = Vec::new();
for (peer, peer_state) in state.peers_snapshot().await {
- if !topology::is_neighbour(state, &peer) {
+ let dormant = peer_state.lock().await.liveness.is_dormant();
+ if !dormant && !topology::is_neighbour(state, &peer) {
continue;
}
- let dormant = peer_state.lock().await.liveness.is_dormant();
let destination = state.transport.destination(&peer);
let transport = destination
.as_ref()
diff --git a/src/swarm/peer/inbound.rs b/src/swarm/peer/inbound.rs
index b4a96e4..b57feaf 100644
--- a/src/swarm/peer/inbound.rs
+++ b/src/swarm/peer/inbound.rs
@@ -58,17 +58,23 @@ pub(crate) async fn handle_message(
remember_peer(state, &peer).await;
- // Any inbound message proves liveness. When we heard from it before tells a
- // restarted peer how long it was away (in our HELLO_REPLY).
- let peer_state = state.get_or_create_peer_state(&peer).await;
- let (reactivated, previously_seen) =
- heard_from(state, &peer, &peer_state, Instant::now(), |_| {}).await;
-
let run = match &message {
transport::ParsedMessage::Hello(hello) => Some(hello.run_id),
transport::ParsedMessage::HelloReply(reply) => Some(reply.sender_run_id),
_ => None,
};
+
+ // Any inbound message proves liveness (but from a run that said farewell: its next
+ // one does). When we heard from it before tells a restarted peer how long it was
+ // away (in our HELLO_REPLY).
+ let peer_state = state.get_or_create_peer_state(&peer).await;
+ let (reactivated, previously_seen) =
+ heard_from(state, &peer, &peer_state, Instant::now(), |peer_state| {
+ if let Some(run) = run {
+ peer_state.returned(run);
+ }
+ })
+ .await;
let same_epoch = observe_peer_epoch(state, &peer, epoch, epoch_seq, run).await;
match message {