aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm/bootstrap.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/swarm/bootstrap.rs')
-rw-r--r--src/swarm/bootstrap.rs35
1 files changed, 22 insertions, 13 deletions
diff --git a/src/swarm/bootstrap.rs b/src/swarm/bootstrap.rs
index a9ab1b2..4f6c072 100644
--- a/src/swarm/bootstrap.rs
+++ b/src/swarm/bootstrap.rs
@@ -18,7 +18,6 @@ use std::collections::HashSet;
use std::path::Path;
use anyhow::{Context, Result, bail};
-use automerge::{ActorId, AutoCommit};
use serde_json::Value as JsonValue;
use tokio::time::Instant;
use tracing::{debug, info, warn};
@@ -28,13 +27,13 @@ use crate::document;
use crate::document::meta::{self, SWARM};
use crate::document::replica::Epoch;
use crate::document::store;
+use crate::document::{ActorId, Document};
use crate::files::{FileKind, Files};
use crate::force::Force;
use crate::remake::snapshot;
use crate::state::AppState;
use crate::swarm::peer::{remember_peer, send_hello_once};
-const BOOTSTRAP_POLL: Duration = Duration::from_millis(500);
/// How often a node that is still joining says why.
const BOOTSTRAP_REPORT: Duration = Duration::from_secs(300);
/// Retrying seeds that didn't resolve: first after this, doubling up to the maximum.
@@ -112,6 +111,7 @@ pub(crate) async fn bootstrap(state: &AppState, seeds: &[String], start: Start)
let mut resolve_retry = RESOLVE_RETRY;
let mut next_resolve = Instant::now();
let mut next_report = Instant::now() + BOOTSTRAP_REPORT;
+ state.transport.on_seeds_found(state.join_progress.clone());
loop {
if let Some(swarm_id) = state.swarm_id().await {
// A node joining a compacted swarm rejoins the newer epoch first; it is
@@ -147,7 +147,19 @@ pub(crate) async fn bootstrap(state: &AppState, seeds: &[String], start: Start)
next_report = now + BOOTSTRAP_REPORT;
report_joining(state, seeds, &unresolved).await;
}
- tokio::time::sleep(BOOTSTRAP_POLL).await;
+ // Until something changes (`join_progress`), or it's time to resolve or report.
+ let resolving = async {
+ if unresolved.is_empty() {
+ std::future::pending().await
+ } else {
+ tokio::time::sleep_until(next_resolve).await
+ }
+ };
+ tokio::select! {
+ () = state.join_progress.notified() => {}
+ () = resolving => {}
+ () = tokio::time::sleep_until(next_report) => {}
+ }
}
}
@@ -156,7 +168,7 @@ fn swarm_id_path() -> Vec<String> {
}
/// The swarm ID the document names, if any.
-fn read_swarm_id(doc: &AutoCommit) -> Option<String> {
+fn read_swarm_id(doc: &Document) -> Option<String> {
match store::read_path(doc, &swarm_id_path()) {
Ok(Some(JsonValue::String(id))) if !id.is_empty() => Some(id),
_ => None,
@@ -184,7 +196,7 @@ impl Origin {
/// A document the node starts from, ready at once: on the swarm and epoch it names.
pub(crate) struct StartingDocument {
/// Under a fresh actor.
- pub(crate) doc: AutoCommit,
+ pub(crate) doc: Document,
pub(crate) epoch: Epoch,
pub(crate) swarm_id: String,
pub(crate) origin: Origin,
@@ -281,7 +293,7 @@ pub(crate) fn starting_document(
/// The swarm and epoch `doc` is on.
fn identify(
- mut doc: AutoCommit,
+ doc: Document,
origin: Origin,
earlier_actors: Vec<ActorId>,
) -> Result<StartingDocument> {
@@ -289,8 +301,7 @@ fn identify(
let Some(swarm_id) = read_swarm_id(&doc) else {
bail!("{what} names no swarm (no _continuum/swarm); it predates swarm IDs in documents");
};
- let epoch =
- snapshot::epoch_of(&mut doc).map_err(|reason| anyhow::anyhow!("{what}: {reason}"))?;
+ let epoch = snapshot::epoch_of(&doc).map_err(|reason| anyhow::anyhow!("{what}: {reason}"))?;
Ok(StartingDocument {
doc,
epoch,
@@ -300,15 +311,13 @@ fn identify(
})
}
-/// A backup to recover from, as `GET /admin/document` saves it, under a fresh actor.
-fn load_backup(path: &Path, files: &Files) -> Result<AutoCommit> {
+/// A backup to recover from, as `GET /admin/document` saves it (`document::load`).
+fn load_backup(path: &Path, files: &Files) -> Result<Document> {
let bytes = files
.read(FileKind::Backup, path)
.with_context(|| format!("Reading the backup {}", path.display()))?
.with_context(|| format!("The backup {} doesn't exist", path.display()))?;
- Ok(AutoCommit::load(&bytes)
- .with_context(|| format!("Loading the backup {}", path.display()))?
- .with_actor(ActorId::random()))
+ crate::document::load(&bytes).with_context(|| format!("Loading the backup {}", path.display()))
}
/// Resolves the seeds in `unresolved`, says HELLO to each that resolves, and keeps the