diff options
Diffstat (limited to 'src/swarm/bootstrap.rs')
| -rw-r--r-- | src/swarm/bootstrap.rs | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/src/swarm/bootstrap.rs b/src/swarm/bootstrap.rs index b725786..3be462e 100644 --- a/src/swarm/bootstrap.rs +++ b/src/swarm/bootstrap.rs @@ -14,6 +14,7 @@ use std::sync::atomic::Ordering; use std::time::Duration; +use std::collections::HashSet; use std::path::Path; use anyhow::{Context, Result, bail}; @@ -57,7 +58,7 @@ pub(crate) async fn bootstrap(state: &AppState, seeds: &[String], start: Start) state.mark_ready(swarm_id).await?; // Members of the swarm still running, if any: they merge with this node, or it // rejoins them if they moved on to a newer epoch. - resolve_seeds(state, &mut seeds.to_vec()).await; + resolve_seeds(state, &mut seeds.to_vec(), &mut HashSet::new()).await; return Ok(()); } if start == Start::Genesis { @@ -85,7 +86,7 @@ pub(crate) async fn bootstrap(state: &AppState, seeds: &[String], start: Start) state.initial_sync_done.store(true, Ordering::Release); state.mark_ready(swarm_id).await?; // Remembered members, if any, to find those still running. - resolve_seeds(state, &mut seeds.to_vec()).await; + resolve_seeds(state, &mut seeds.to_vec(), &mut HashSet::new()).await; return Ok(()); } @@ -98,6 +99,7 @@ pub(crate) async fn bootstrap(state: &AppState, seeds: &[String], start: Start) } let mut unresolved: Vec<String> = seeds.to_vec(); + let mut failing = HashSet::new(); let mut resolve_retry = RESOLVE_RETRY; let mut next_resolve = Instant::now(); let mut next_report = Instant::now() + BOOTSTRAP_REPORT; @@ -114,7 +116,7 @@ pub(crate) async fn bootstrap(state: &AppState, seeds: &[String], start: Start) let now = Instant::now(); if !unresolved.is_empty() && now >= next_resolve { - resolve_seeds(state, &mut unresolved).await; + resolve_seeds(state, &mut unresolved, &mut failing).await; if !unresolved.is_empty() { next_resolve = now + resolve_retry; resolve_retry = (resolve_retry * 2).min(RESOLVE_RETRY_MAX); @@ -174,20 +176,33 @@ pub(crate) fn load_backup(path: &Path) -> Result<Backup> { } /// Resolves the seeds in `unresolved`, says HELLO to each that resolves, and keeps the -/// rest for later. -async fn resolve_seeds(state: &AppState, unresolved: &mut Vec<String>) { +/// rest for later. Warns once per seed that fails (`failing` remembers which), and says +/// when such a seed resolves after all. +async fn resolve_seeds( + state: &AppState, + unresolved: &mut Vec<String>, + failing: &mut HashSet<String>, +) { let mut still = Vec::new(); for seed in unresolved.drain(..) { match state.transport.resolve_seed(&seed).await { Ok(peer) => { - debug!(seed = %seed, peer = %peer, "Resolved seed"); + if failing.remove(&seed) { + info!(seed = %seed, peer = %peer, "Seed resolves now"); + } else { + debug!(seed = %seed, peer = %peer, "Resolved seed"); + } remember_peer(state, &peer).await; if let Err(error) = send_hello_once(state, &peer).await { warn!(peer = %peer, error = %format!("{error:#}"), "Initial HELLO failed; will retry"); } } Err(error) => { - warn!(seed = %seed, error = %error, "Seed doesn't resolve; will retry"); + if failing.insert(seed.clone()) { + warn!(seed = %seed, error = %error, "Seed doesn't resolve; trying again until it does"); + } else { + debug!(seed = %seed, error = %error, "Seed still doesn't resolve"); + } still.push(seed); } } |
