From 36a4a54b1c9204d72e405f5bbfa2a1b595ccba04 Mon Sep 17 00:00:00 2001 From: tv Date: Fri, 6 Nov 2026 20:22:03 +0100 Subject: flood dissemination --- src/swarm/dissemination.rs | 3 +++ src/swarm/flood.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++++ src/swarm/mod.rs | 1 + 3 files changed, 69 insertions(+) create mode 100644 src/swarm/flood.rs (limited to 'src/swarm') diff --git a/src/swarm/dissemination.rs b/src/swarm/dissemination.rs index 93ad4e9..9763449 100644 --- a/src/swarm/dissemination.rs +++ b/src/swarm/dissemination.rs @@ -139,6 +139,8 @@ pub(crate) enum Kind { WritersTrees, /// PlumTree (`swarm::plumtree`). Plumtree, + /// Flooding (`swarm::flood`). + Flood, } impl Kind { @@ -146,6 +148,7 @@ impl Kind { match self { Kind::WritersTrees => std::sync::Arc::new(crate::swarm::tree::WritersTrees), Kind::Plumtree => std::sync::Arc::new(crate::swarm::plumtree::PlumTree::default()), + Kind::Flood => std::sync::Arc::new(crate::swarm::flood::Flood), } } } 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 { + 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 { + 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, + carried: bool, + authors: &[(String, Vec)], + ) { + let _ = peer; + if writer.is_some() && carried && authors.is_empty() { + state.stats.tree_from_other(); + } + } +} diff --git a/src/swarm/mod.rs b/src/swarm/mod.rs index 63ddcfa..ccffaa0 100644 --- a/src/swarm/mod.rs +++ b/src/swarm/mod.rs @@ -7,6 +7,7 @@ pub(crate) mod bootstrap; pub(crate) mod changes; pub(crate) mod dissemination; pub(crate) mod document_file; +pub(crate) mod flood; pub(crate) mod hop; pub(crate) mod hyparview; pub(crate) mod links; -- cgit v1.3.1