summaryrefslogtreecommitdiffstats
path: root/src/remake/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/remake/mod.rs')
-rw-r--r--src/remake/mod.rs37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/remake/mod.rs b/src/remake/mod.rs
index 0895931..ca17956 100644
--- a/src/remake/mod.rs
+++ b/src/remake/mod.rs
@@ -7,6 +7,7 @@
//! * `records`: the replicated remake records under `_continuum/remakes/<id>`.
//! * `coordinator`: proposal, vote count and decision on the node that was asked.
//! * `vote`: who votes, for which remake, and when a remake has its majority.
+//! * `content`: the new document of a `replace`/`import` remake, fetched by every voter.
//! * `switch`: switching this node to a committed epoch (worker).
//! * `catchup`: rejoining a newer epoch from peers (late, new or failed nodes), then
//! replaying or quarantining this node's own missing changes.
@@ -20,6 +21,7 @@
mod api;
mod catchup;
+mod content;
mod coordinator;
mod delta;
mod kind;
@@ -68,6 +70,21 @@ pub(crate) trait Host: Clone + Send + Sync + 'static {
/// alive recently enough, read from `doc`.
fn electorate(&self, doc: &AutoCommit, now_ms: u64) -> Vec<String>;
+ /// Downloads a change from peers on the local epoch, in chunks from several at once,
+ /// checked against its hash.
+ fn fetch_change(
+ &self,
+ hash: automerge::ChangeHash,
+ ) -> impl Future<Output = anyhow::Result<automerge::Change>> + Send;
+
+ /// Downloads content by its BLAKE3 hash from peers on the local epoch, checked
+ /// against it.
+ fn fetch_content(&self, hash: [u8; 32])
+ -> impl Future<Output = anyhow::Result<Vec<u8>>> + Send;
+
+ /// Starts sync with every peer (e.g. after holding it back).
+ fn request_sync(&self);
+
fn is_node_ready(&self) -> impl Future<Output = bool> + Send;
/// Known (not forgotten) peers.
@@ -124,10 +141,30 @@ pub(crate) struct PeerSummary {
pub(crate) id: String,
/// Not dormant.
pub(crate) active: bool,
+ /// Completed the handshake and belongs to our swarm. A peer that merely sent us
+ /// something (a node of another swarm on the same network, a stranger before
+ /// admission) is not one, and nothing it advertises is followed.
+ pub(crate) member: bool,
+ /// What it last said about being ready; None before it said anything.
+ pub(crate) ready: Option<bool>,
/// The epoch the peer last advertised.
pub(crate) epoch: Option<Epoch>,
}
+impl PeerSummary {
+ /// A peer whose epoch can be followed and downloaded from: an active member that
+ /// holds the document it advertises. A rejoining peer advertises its target epoch
+ /// with an empty document and `ready: false`.
+ pub(crate) fn serves_epoch(&self, epoch: Epoch) -> bool {
+ self.serves() && self.epoch == Some(epoch)
+ }
+
+ /// An active, ready member.
+ pub(crate) fn serves(&self) -> bool {
+ self.active && self.member && self.ready == Some(true)
+ }
+}
+
/// Admin routes. Merged into the authenticated part of the node's router.
/// Largest remake request (bytes). The proposal carries the new document to every
/// node in one sync message, which Mycelium must deliver within its deadline, so