diff options
| author | tv <tv@krebsco.de> | 2026-10-25 12:55:27 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-25 12:55:27 +0100 |
| commit | d6620dc266b593e9ed269bcb7e65d3d8c9710d27 (patch) | |
| tree | 15d86e3fa2e0ef3b2cea6907c7b778a8ee6ed2b4 /src/main.rs | |
| parent | 9845a07960fa083db0b0c7e2312f98706e9684cb (diff) | |
add possibility to start with a document
The --recover-from option allows a node start with a given document.
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/src/main.rs b/src/main.rs index 4cfae66..d6773eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -116,12 +116,21 @@ async fn main() -> Result<()> { let (change_tx, _) = watch::channel(0_u64); let (change_events, _) = broadcast::channel(256); - let initial_epoch = match args.debug_epoch { - Some(generation) => Epoch { + let recovered = match &args.recover_from { + Some(path) => Some(bootstrap::load_backup(path)?), + None => None, + }; + let (initial_doc, recovered_epoch, recovered_swarm) = match recovered { + Some((doc, epoch, swarm_id)) => (doc, Some(epoch), Some(swarm_id)), + None => (AutoCommit::new(), None, None), + }; + let initial_epoch = match (recovered_epoch, args.debug_epoch) { + (Some(epoch), _) => epoch, + (None, Some(generation)) => Epoch { generation, id: [0xee; 32], }, - None => Epoch::GENESIS, + (None, None) => Epoch::GENESIS, }; let (epoch_tx, _) = watch::channel(initial_epoch); debug!(epoch = %initial_epoch, "Local epoch"); @@ -133,7 +142,7 @@ async fn main() -> Result<()> { debug!(local_id = mycelium_transport.local_id(), "Transport ready"); let state = AppState { - doc: Arc::new(RwLock::new(Replica::new(initial_epoch, AutoCommit::new()))), + doc: Arc::new(RwLock::new(Replica::new(initial_epoch, initial_doc))), epoch_tx, lifecycle: Arc::new(RwLock::new(NodeLifecycle::Joining { discovered_swarm_id: None, @@ -179,10 +188,31 @@ async fn main() -> Result<()> { trace!("Application state initialized"); - // Join the remembered swarm and no other; HELLOs claim it. - if let Some(remembered) = remembered { - state.set_expected_swarm_id(remembered.swarm_id).await?; - } + // Join the remembered swarm and no other; HELLOs claim it. A backup to recover from + // names its swarm itself, which wins. + let start = match recovered_swarm { + Some(swarm_id) => { + if let Some(remembered) = remembered.filter(|r| r.swarm_id != swarm_id) { + warn!( + backup = %swarm_id, + remembered = %remembered.swarm_id, + "The backup is of another swarm than the remembered one; recovering the backup's" + ); + } + state.set_expected_swarm_id(swarm_id).await?; + bootstrap::Start::Recovered + } + None => { + if let Some(remembered) = remembered { + state.set_expected_swarm_id(remembered.swarm_id).await?; + } + if args.genesis { + bootstrap::Start::Genesis + } else { + bootstrap::Start::Join + } + } + }; let consumer_state = state.clone(); tokio::spawn(async move { @@ -215,7 +245,7 @@ async fn main() -> Result<()> { tokio::spawn(remake::run_worker(state.clone())); trace!("Remake worker task spawned"); - let joining = bootstrap::bootstrap(&state, &seeds, args.genesis); + let joining = bootstrap::bootstrap(&state, &seeds, start); tokio::select! { joined = joining => joined.context("Joining swarm")?, _ = stopped(stop.clone()) => { |
