aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm/dissemination.rs
blob: 1d92b06028c021c44d4e91f5fa2d2036737bf8ab (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
//! How a change reaches every member: whom a node sends a writer's changes to at once,
//! and whom it leaves to the announcement rounds (`swarm::relay`, which repair what it
//! misses: announcements, pulls, the slow round). Writers' trees (`swarm::tree`) are
//! one way; others can be tried against them in the benchmark (`docs/future-work.md`,
//! Swappable topology and dissemination). One per swarm: a node's part in passing a
//! change on is worked out by itself and by its neighbours, and must agree.
//!
//! What every way keeps: the base underneath, pairs of neighbours syncing with
//! Automerge, which delivers everything in the end; a way only decides whom to push to
//! first, and so how soon.

use async_trait::async_trait;

use crate::document::ChangeHash;
use crate::state::AppState;
use crate::swarm::tree::Plan;

#[async_trait]
pub(crate) trait Dissemination: Send + Sync + 'static {
    /// Its name (in logs, and once chosen by the swarm, in the document).
    fn name(&self) -> &'static str;

    /// Our part in passing on `writer`'s changes (by its pair key, `topology::pair_key`):
    /// whom we send them to at once, and how the announcement rounds treat our other
    /// neighbours (`Plan`). None: we have no part, and announcements do it all.
    async fn plan(&self, state: &AppState, writer: u64) -> Option<Plan>;

    /// `writer`'s `changes` came from `from` (none: we had them already, and they came
    /// as the writer's now): passed on at once to those we send them to, the others
    /// counted as having them where they get them elsewhere. Returns our part, as
    /// `plan`.
    async fn forward(
        &self,
        state: &AppState,
        writer: u64,
        from: &str,
        changes: &[ChangeHash],
    ) -> Option<Plan>;

    /// What a sync message from `peer` says about how well this works (`/admin/stats`):
    /// whether it came as `writer`'s and `carried` changes, and the new changes it
    /// brought, by author. Not while catching up.
    async fn note_arrival(
        &self,
        state: &AppState,
        peer: &str,
        writer: Option<u64>,
        carried: bool,
        authors: &[(String, Vec<ChangeHash>)],
    );
}