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/state/host.rs | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'src/state/host.rs') diff --git a/src/state/host.rs b/src/state/host.rs index a878381..24a989e 100644 --- a/src/state/host.rs +++ b/src/state/host.rs @@ -13,7 +13,7 @@ use tracing::debug; use super::{AppState, HelloState, NodeLifecycle, StaleView, Standing}; use crate::document::replica::Epoch; use crate::document::store::ChangeSet; -use crate::document::{ChangeHash, Document}; +use crate::document::{ChangeHash, Document, ReadDoc, Transaction}; use crate::remake::{Host, PeerSummary, RemakeState}; impl AppState { @@ -86,7 +86,7 @@ impl Host for AppState { crate::swarm::skew::measure(self).await } - fn electorate(&self, doc: &Document, now: crate::clock::UnixMillis) -> Vec { + fn electorate(&self, doc: &impl ReadDoc, now: crate::clock::UnixMillis) -> Vec { crate::swarm::members::electorate(doc, now.as_u64(), self.electorate_window) } @@ -218,7 +218,7 @@ impl Host for AppState { fn commit_doc(&self, f: F) -> impl Future> + Send where - F: FnOnce(&mut Document) -> Result + Send + 'static, + F: FnOnce(&mut Transaction<'_>) -> Result + Send + 'static, T: Send + 'static, E: Send + 'static, { @@ -226,13 +226,39 @@ impl Host for AppState { async move { state.mutate_doc(f).await } } + fn apply_change( + &self, + change: crate::document::Change, + ) -> impl Future> + Send { + let state = self.clone(); + async move { + tokio::task::spawn_blocking(move || { + let result = { + let mut replica = state.doc.blocking_write(); + let result = replica + .apply_changes([change]) + .map_err(|error| error.to_string()); + replica.refresh_heads(); + result + }; // lock released before notifying + + if result.is_ok() { + state.publish_change(); + } + result + }) + .await + .expect("document write task panicked") + } + } + fn switch_epoch( &self, epoch: Epoch, f: F, ) -> impl Future> + Send where - F: FnOnce(&mut Document) -> Result + Send + 'static, + F: FnOnce(&Document) -> Result + Send + 'static, E: Send + 'static, { let state = self.clone(); @@ -241,7 +267,7 @@ impl Host for AppState { let state = state.clone(); tokio::task::spawn_blocking(move || -> Result { let mut replica = state.doc.blocking_write(); - let new_doc = f(&mut replica.doc)?; + let new_doc = f(&replica.doc)?; let old_doc = std::mem::replace(&mut replica.doc, new_doc); replica.epoch = epoch; replica.epoch_seq += 1; -- cgit v1.3.1