aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm/flood.rs
blob: 39cb096f36f22d93290040fb48632233be826e2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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();
        }
    }
}