aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm/flood.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-06 20:22:03 +0100
committertv <tv@krebsco.de>2026-11-06 20:22:03 +0100
commit36a4a54b1c9204d72e405f5bbfa2a1b595ccba04 (patch)
treeebf7c8cf135ebb2684f78a42f2876a0675300624 /src/swarm/flood.rs
parent5994b49412c058079639585501a78e6458fdbb6f (diff)
flood dissemination
Diffstat (limited to 'src/swarm/flood.rs')
-rw-r--r--src/swarm/flood.rs65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/swarm/flood.rs b/src/swarm/flood.rs
new file mode 100644
index 0000000..39cb096
--- /dev/null
+++ b/src/swarm/flood.rs
@@ -0,0 +1,65 @@
+//! Flooding (`--dissemination flood`, `swarm::dissemination`): a node pushes every
+//! change it gets, at once, to every neighbour but the one it came from. The broadcast
+//! HyParView's paper pairs its views with, and what PlumTree prunes down to a tree: the
+//! baseline the others are measured against. Every link carries every change about
+//! twice (once each way, where both ends got it before the other's push came), so the
+//! messages grow with the neighbours each member keeps; the latency is that of the
+//! fastest path, with no tree to compute or to repair.
+
+use async_trait::async_trait;
+
+use crate::document::ChangeHash;
+use crate::state::AppState;
+use crate::swarm::dissemination::{Dissemination, pass_on};
+use crate::swarm::topology;
+use crate::swarm::tree::Plan;
+
+pub(crate) struct Flood;
+
+#[async_trait]
+impl Dissemination for Flood {
+ fn name(&self) -> &'static str {
+ "flood"
+ }
+
+ /// Every neighbour gets the writer's changes at once, and is told of them in the slow
+ /// round too (`Plan::alone`): with every neighbour a child, no round would tell
+ /// anyone, and a push lost on a lossy link waited for the next write, or a keepalive.
+ async fn plan(&self, state: &AppState, writer: u64) -> Option<Plan> {
+ let _ = writer;
+ let neighbours = topology::our_neighbours(state);
+ Some(Plan {
+ children: neighbours.clone(),
+ alone: neighbours,
+ uncovered: Vec::new(),
+ covered: Vec::new(),
+ })
+ }
+
+ async fn forward(
+ &self,
+ state: &AppState,
+ writer: u64,
+ from: &str,
+ changes: &[ChangeHash],
+ ) -> Option<Plan> {
+ let plan = self.plan(state, writer).await?;
+ Some(pass_on(state, writer, from, changes, plan).await)
+ }
+
+ /// Counted as the trees' counters count (`/admin/stats`): a push with nothing new as
+ /// a message from another than the parent.
+ async fn note_arrival(
+ &self,
+ state: &AppState,
+ peer: &str,
+ writer: Option<u64>,
+ carried: bool,
+ authors: &[(String, Vec<ChangeHash>)],
+ ) {
+ let _ = peer;
+ if writer.is_some() && carried && authors.is_empty() {
+ state.stats.tree_from_other();
+ }
+ }
+}