From 9c12bf2e8815dc9b42be62f1e1fd2932dd02938b Mon Sep 17 00:00:00 2001 From: tv Date: Sat, 31 Oct 2026 19:53:27 +0100 Subject: use Automerge as Document instead of AutoCommit This allows a lot of operations to drop mut. --- src/document/sync.rs | 55 +++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 29 deletions(-) (limited to 'src/document/sync.rs') diff --git a/src/document/sync.rs b/src/document/sync.rs index 625d805..2a24007 100644 --- a/src/document/sync.rs +++ b/src/document/sync.rs @@ -14,7 +14,7 @@ use automerge::sync::{self, SyncDoc}; use tokio::time::Instant; use tracing::debug; -use super::Document; +use super::{Document, ReadDoc}; use crate::backoff::Backoff; use crate::swarm::throughput::SyncBytes; use crate::transport::SyncPayload; @@ -126,7 +126,7 @@ impl SyncSession { /// peer so far (`swarm::throughput`). pub(crate) fn generate( &mut self, - doc: &mut Document, + doc: &Document, now: Instant, bytes: SyncBytes, ) -> Option { @@ -135,7 +135,7 @@ impl SyncSession { self.state.last_sent_heads.clone(), self.state.have_responded, ); - let message = doc.sync().generate_sync_message(&mut self.state); + let message = doc.generate_sync_message(&mut self.state); let in_step = self.state.their_heads.as_ref() == Some(&doc.get_heads()); let sent: Vec<_> = self .state @@ -167,7 +167,7 @@ impl SyncSession { message: Received, ) -> Result<(), AutomergeError> { self.delta_offered = false; - doc.sync().receive_sync_message(&mut self.state, message.0) + doc.receive_sync_message(&mut self.state, message.0) } /// The message just generated is too large to send in one piece: take back what it @@ -194,7 +194,7 @@ impl SyncSession { /// Whether `doc` holds everything the peer had when it last told us its heads: they /// are known, not empty (empty heads are "contained" in every document, so they /// prove nothing), and all in `doc`. - pub(crate) fn have_all_theirs(&self, doc: &mut Document) -> bool { + pub(crate) fn have_all_theirs(&self, doc: &Document) -> bool { self.state.their_heads.as_ref().is_some_and(|heads| { !heads.is_empty() && heads @@ -392,16 +392,16 @@ mod tests { change(&mut a, |a| a.put(automerge::ROOT, "early", 1).unwrap()); // Until in step. for _ in 0..10 { - let to_b = a.sync().generate_sync_message(&mut at_a); - let to_a = b.sync().generate_sync_message(&mut at_b); + let to_b = a.generate_sync_message(&mut at_a); + let to_a = b.generate_sync_message(&mut at_b); if to_b.is_none() && to_a.is_none() { break; } if let Some(m) = to_b { - b.sync().receive_sync_message(&mut at_b, m).unwrap(); + b.receive_sync_message(&mut at_b, m).unwrap(); } if let Some(m) = to_a { - a.sync().receive_sync_message(&mut at_a, m).unwrap(); + a.receive_sync_message(&mut at_a, m).unwrap(); } } assert_eq!(a.get_heads(), b.get_heads()); @@ -411,21 +411,21 @@ mod tests { a.put(automerge::ROOT, format!("lost{i}"), i).unwrap() }); } - let _lost = a.sync().generate_sync_message(&mut at_a).unwrap(); + let _lost = a.generate_sync_message(&mut at_a).unwrap(); change(&mut a, |a| a.put(automerge::ROOT, "last", 6).unwrap()); at_a.in_flight = false; // As after our reply timeout. - let last = a.sync().generate_sync_message(&mut at_a).unwrap(); + let last = a.generate_sync_message(&mut at_a).unwrap(); assert_eq!(last.changes.len(), 1); - b.sync().receive_sync_message(&mut at_b, last).unwrap(); + b.receive_sync_message(&mut at_b, last).unwrap(); // b asks for the fifth, saying nothing of what it has. - let ask = b.sync().generate_sync_message(&mut at_b).unwrap(); + let ask = b.generate_sync_message(&mut at_b).unwrap(); assert!(ask.have.is_empty() && ask.need.len() == 1); - a.sync().receive_sync_message(&mut at_a, ask).unwrap(); + a.receive_sync_message(&mut at_a, ask).unwrap(); assert!(answer_for_everything_since_shared(&mut at_a)); // All since the shared heads, in one message (here the whole document: more // than a third of it is missing). - let answer = a.sync().generate_sync_message(&mut at_a).unwrap(); - b.sync().receive_sync_message(&mut at_b, answer).unwrap(); + let answer = a.generate_sync_message(&mut at_a).unwrap(); + b.receive_sync_message(&mut at_b, answer).unwrap(); assert_eq!(b.get_heads(), a.get_heads()); // A message with what it has is left alone. assert!(!answer_for_everything_since_shared(&mut at_b)); @@ -485,13 +485,13 @@ mod tests { let bytes = SyncBytes::default(); // a opens, b answers with its (empty) heads, then a sends the changes. - let opening = a.generate(&mut ours, now, bytes).unwrap(); + let opening = a.generate(&ours, now, bytes).unwrap(); a.send_succeeded(a.id()); b.receive(&mut theirs, decode(&opening).unwrap()).unwrap(); - let answer = b.generate(&mut theirs, now, bytes).unwrap(); + let answer = b.generate(&theirs, now, bytes).unwrap(); b.send_succeeded(b.id()); a.receive(&mut ours, decode(&answer).unwrap()).unwrap(); - let carrying = a.generate(&mut ours, now, bytes).unwrap(); + let carrying = a.generate(&ours, now, bytes).unwrap(); let carried = carrying.0.len(); assert!(carried > 4_000, "the changes took {carried} bytes"); @@ -506,7 +506,7 @@ mod tests { .is_some() ); assert!(!a.delta_offered); - let again = a.generate(&mut ours, now, bytes).unwrap(); + let again = a.generate(&ours, now, bytes).unwrap(); let carried_again = again.0.len(); assert!(carried_again > 4_000, "sent again in {carried_again} bytes"); } @@ -531,27 +531,24 @@ mod tests { let bytes = SyncBytes::default(); // b (joining) opens; a's answer would carry everything: withdrawn for a delta. - let opening = b.generate(&mut theirs, now, bytes).unwrap(); + let opening = b.generate(&theirs, now, bytes).unwrap(); b.send_succeeded(b.id()); a.receive(&mut ours, decode(&opening).unwrap()).unwrap(); - assert!(a.generate(&mut ours, now, bytes).is_some()); + assert!(a.generate(&ours, now, bytes).is_some()); a.withdraw_for_delta(); a.send_succeeded(a.id()); // b loads the delta and tells a its heads, which are a's now. theirs.merge(&mut ours.clone()).unwrap(); - assert!( - !b.have_all_theirs(&mut theirs), - "b hasn't heard a's heads yet" - ); - let after_delta = b.generate(&mut theirs, now, bytes).unwrap(); + assert!(!b.have_all_theirs(&theirs), "b hasn't heard a's heads yet"); + let after_delta = b.generate(&theirs, now, bytes).unwrap(); b.send_succeeded(b.id()); a.receive(&mut ours, decode(&after_delta).unwrap()).unwrap(); let answer = a - .generate(&mut ours, now, bytes) + .generate(&ours, now, bytes) .expect("a answers with its heads"); b.receive(&mut theirs, decode(&answer).unwrap()).unwrap(); - assert!(b.have_all_theirs(&mut theirs)); + assert!(b.have_all_theirs(&theirs)); } } -- cgit v1.3.1