diff options
| author | tv <tv@krebsco.de> | 2026-11-09 20:29:32 +0000 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-09 22:20:00 +0100 |
| commit | 152890f321075beede075314d37ff6451604c359 (patch) | |
| tree | 352bbdeabea55735d9bafe78cba24b58a1182c2f /src/main.rs | |
| parent | 5f7e29cec4333715346b4bf3195633db93449d9d (diff) | |
document file: a clean stop marked, and `--keep-actor` writes on as the same actor
A node writes as a fresh Automerge actor at each start, so no change number of an actor
comes twice: one sent before a crash but not yet appended to the document file would
otherwise be made again, differently. An epoch thus gathers a writer per start, and
every transfer of its history carries a signature per writer.
The document file now says when it holds everything the node wrote:
* at a clean stop, after the last append, an empty `Closed` record, only where the
file is up to the document's heads (ready, not rejoining);
* as a node starts on the file, before anything is written, an empty `Opened` record,
so a crash from then on leaves a file without the mark;
* the header names the actor the node writes with (`current`).
With `--keep-actor` (off by default; needs `--document-file`), a node starting on a
file that ends with `Closed` writes on as that actor. A crash, a drop, a switch or a
rejoin still starts a fresh one, so an epoch's writers come to one per node plus one
per such event. lifecycle.md says so.
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/src/main.rs b/src/main.rs index 880d793..7c819e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -165,18 +165,37 @@ async fn main() -> Result<()> { &files, &force, )?; - let (initial_doc, starting_epoch, starting_swarm, earlier_actors, initial_signatures) = - match starting { - Some(starting) => ( - starting.doc, - Some(starting.epoch), - Some((starting.swarm_id, starting.origin)), - starting.earlier_actors, - starting.signatures, - ), - None => (Document::new(), None, None, Vec::new(), Vec::new()), - }; + let ( + initial_doc, + starting_epoch, + starting_swarm, + earlier_actors, + initial_signatures, + resumable, + ) = match starting { + Some(starting) => ( + starting.doc, + Some(starting.epoch), + Some((starting.swarm_id, starting.origin)), + starting.earlier_actors, + starting.signatures, + starting.resumable, + ), + None => (Document::new(), None, None, Vec::new(), Vec::new(), None), + }; let mut initial_doc = initial_doc; + // Writing on as the actor of before, where this node stopped cleanly: everything it + // wrote as that one is in the document, so no change of it comes twice. + match resumable.filter(|_| args.keep_actor) { + Some(actor) => { + info!(actor = %actor, "Writing on as the actor of before (--keep-actor)"); + initial_doc.set_actor(actor); + } + None if args.keep_actor && starting_epoch.is_some() => { + info!("Writing as a fresh actor: this node didn't stop cleanly (--keep-actor)"); + } + None => {} + } if let Some(spec) = &args.remake { remake::remake_genesis(spec, &files, &mut initial_doc) .with_context(|| format!("Making the genesis document (--remake {spec})"))?; @@ -228,6 +247,11 @@ async fn main() -> Result<()> { args.document_rewrite, )) }); + // A clean stop's mark undone before anything is written: a crash from here on + // leaves a file that doesn't say so. + if let Some(file) = &document_file { + file.open(); + } let node = node::Node::new(node::NodeConfig { transport, identity: Some(transport::identity::IdentityConfig { @@ -367,6 +391,7 @@ async fn main() -> Result<()> { swarm::peer::farewell(&state).await; swarm::state_file::update(&state, true).await; swarm::document_file::flush(&state).await; + swarm::document_file::close(&state).await; Ok(()) } |
