aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm/tree.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/swarm/tree.rs')
-rw-r--r--src/swarm/tree.rs44
1 files changed, 43 insertions, 1 deletions
diff --git a/src/swarm/tree.rs b/src/swarm/tree.rs
index b9491b3..064f5b9 100644
--- a/src/swarm/tree.rs
+++ b/src/swarm/tree.rs
@@ -363,13 +363,55 @@ pub(crate) struct Latencies {
/// neighbours said); None if we have none, or no tree is known.
#[cfg(test)]
pub(crate) async fn own_parent(state: &AppState, writer: &str) -> Option<String> {
- let (graph, distance) = distances(state, topology::pair_key(writer))?;
+ our_parent(state, topology::pair_key(writer)).await
+}
+
+/// `own_parent`, of the writer by pair key.
+async fn our_parent(state: &AppState, writer: u64) -> Option<String> {
+ let (graph, distance) = distances(state, 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);
parent(&graph, &distance, &reached, &round_trip, state.local_id()).map(str::to_owned)
}
+/// Whether the trees work, from what arrives (`swarm::stats`, `/admin/stats`): a sync
+/// message from `peer` along `writer`'s tree that `carried` changes, where we have a
+/// parent in it and it isn't `peer` (a double send, or views of the tree that differ);
+/// the changes of `authors` (by author) that came with a message along no tree, where
+/// we have a parent in their writer's tree (the tree didn't bring them, or not first).
+/// Not while catching up, when everything comes another way.
+pub(crate) async fn note_arrival(
+ state: &AppState,
+ peer: &str,
+ writer: Option<u64>,
+ carried: bool,
+ authors: &[(String, Vec<crate::document::ChangeHash>)],
+) {
+ match writer {
+ Some(writer) if carried => {
+ if our_parent(state, writer)
+ .await
+ .is_some_and(|parent| parent != peer)
+ {
+ state.stats.tree_from_other();
+ }
+ }
+ None => {
+ for (author, changes) in authors {
+ if author != state.local_id()
+ && our_parent(state, topology::pair_key(author))
+ .await
+ .is_some()
+ {
+ state.stats.tree_missed(changes.len());
+ }
+ }
+ }
+ Some(_) => {}
+ }
+}
+
/// Where we are in `writer`'s tree, as we see it: our distance from the writer, our
/// parent (`parent`), and the neighbours we reach that come before us (whom we could
/// take). None while the member list isn't known, or the writer or we aren't in it.