aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/api/dashboard/mod.rs44
-rw-r--r--src/swarm/tree.rs18
2 files changed, 16 insertions, 46 deletions
diff --git a/src/api/dashboard/mod.rs b/src/api/dashboard/mod.rs
index 7d940c9..e86475f 100644
--- a/src/api/dashboard/mod.rs
+++ b/src/api/dashboard/mod.rs
@@ -715,41 +715,16 @@ struct TreeQuery {
writer: String,
}
-/// `GET /admin/dashboard/tree?writer=…`: the writer's tree (`swarm::tree`), as this node
-/// computes it from the member list and the links members report (whom each reaches,
-/// and how far: its round trip, as a bucket, `rtt::bucket`; one that reports none counts
-/// as reaching its neighbours by the member list): every member's parent, `null` for
-/// one without. `404` if the writer isn't a member.
+/// `GET /admin/dashboard/tree?writer=…`: the writer's tree (`swarm::tree::whole`), as
+/// this node computes it: from the member list, and whom it and its neighbours reach
+/// and how far, as they said (others as reaching their neighbours by the member list):
+/// every member's parent, `null` for one without. `404` if the writer isn't a member.
async fn writer_tree(
Extension(hub): Extension<Arc<Hub>>,
Query(query): Query<TreeQuery>,
) -> Response {
let state = &hub.state;
- let mut reports: BTreeMap<String, Vec<Link>> = state
- .links
- .replies()
- .into_iter()
- .map(|(member, _, links)| (member, links))
- .collect();
- reports.insert(state.local_id().to_owned(), links::own_links(state).await);
- let reaches: BTreeMap<&str, BTreeSet<String>> = reports
- .iter()
- .map(|(member, links)| (member.as_str(), reached_by(links)))
- .collect();
- let reached = |by: &str, member: &str| {
- reaches
- .get(by)
- .is_none_or(|reached| reached.contains(member))
- };
- let round_trip = |by: &str, member: &str| {
- let rtt = reports
- .get(by)
- .and_then(|links| links.iter().find(|link| link.peer == member))
- .and_then(|link| link.rtt_us)
- .map(|us| std::time::Duration::from_micros(u64::from(us)));
- crate::swarm::rtt::bucket(rtt, None)
- };
- match crate::swarm::tree::whole(state, &query.writer, &reached, &round_trip) {
+ match crate::swarm::tree::whole(state, &query.writer).await {
Some(parents) => {
axum::Json(json!({ "writer": query.writer, "parents": parents })).into_response()
}
@@ -757,15 +732,6 @@ async fn writer_tree(
}
}
-/// Whom a member reaches, by its links: those neither dormant nor down.
-fn reached_by(links: &[Link]) -> BTreeSet<String> {
- links
- .iter()
- .filter(|link| !link.dormant && !link.down)
- .map(|link| link.peer.clone())
- .collect()
-}
-
/// `GET /admin/dashboard/state`: the latest snapshot, for a client that wants it whole.
async fn current_state(Extension(hub): Extension<Arc<Hub>>) -> Response {
hub.want();
diff --git a/src/swarm/tree.rs b/src/swarm/tree.rs
index db3e920..4d5afd8 100644
--- a/src/swarm/tree.rs
+++ b/src/swarm/tree.rs
@@ -175,18 +175,22 @@ fn parent<'g>(
})
}
-/// `writer`'s whole tree, as far as `reached` knows whom each member reaches and
-/// `round_trip` how far (the dashboard's map, from the links members report): every
-/// member's parent, None for those without one (they get the writer's changes by
-/// announcement). None while the member list isn't known, or the writer isn't in it.
+/// `writer`'s whole tree, as this node knows it (the dashboard's map): whom it and its
+/// neighbours reach and how far, as they said (`known_reaches`), the others by the
+/// member list's graph, as every member computes its own part (`plan`): every member's
+/// parent, None for those without one (they get the writer's changes by announcement).
+/// None while the member list isn't known, or the writer isn't in it.
#[cfg_attr(not(feature = "dashboard"), allow(dead_code))]
-pub(crate) fn whole(
+pub(crate) async fn whole(
state: &AppState,
writer: &str,
- reached: &dyn Fn(&str, &str) -> bool,
- round_trip: &dyn Fn(&str, &str) -> u8,
) -> Option<BTreeMap<String, Option<String>>> {
let (graph, distance) = distances(state, topology::pair_key(writer))?;
+ let known = known_reaches(state, &graph).await;
+ let reached = |by: &str, member: &str| known.reached(by, member);
+ let round_trip = |by: &str, member: &str| known.round_trip(by, member);
+ let (reached, round_trip): (&dyn Fn(&str, &str) -> bool, &dyn Fn(&str, &str) -> u8) =
+ (&reached, &round_trip);
Some(
graph
.keys()