//! 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; /// `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; /// 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, carried: bool, authors: &[(String, Vec)], ); }