summaryrefslogtreecommitdiffstats
path: root/src/remake/catchup.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/remake/catchup.rs')
-rw-r--r--src/remake/catchup.rs32
1 files changed, 23 insertions, 9 deletions
diff --git a/src/remake/catchup.rs b/src/remake/catchup.rs
index cad5a22..4feb70e 100644
--- a/src/remake/catchup.rs
+++ b/src/remake/catchup.rs
@@ -31,7 +31,7 @@ use std::collections::{BTreeMap, HashMap};
use std::convert::Infallible;
use std::time::Duration;
-use automerge::{AutoCommit, ChangeHash};
+use automerge::{ActorId, AutoCommit, ChangeHash};
use tokio::time::Instant;
use tracing::{debug, error, info, warn};
@@ -177,8 +177,12 @@ async fn start<H: Host>(host: &H, local: Epoch, target: Epoch, attempts: u32) {
host.set_stale_view(Some((local, copy)));
}
let was_ready = host.suspend().await;
+ let actor = ActorId::random();
+ host.remake().add_own_actor(actor.clone());
let old = match host
- .switch_epoch(target, |_live| Ok::<_, Infallible>(AutoCommit::new()))
+ .switch_epoch(target, move |_live| {
+ Ok::<_, Infallible>(AutoCommit::new().with_actor(actor))
+ })
.await
{
Ok(old) => old,
@@ -276,7 +280,9 @@ async fn finish<H: Host>(host: &H) {
// Everything heavy runs on a copy, without a lock.
let copy = host.read_doc(|doc| doc.clone()).await;
- let prepared = tokio::task::spawn_blocking(move || prepare(copy, old, previous, target)).await;
+ let own = host.remake().own_actors();
+ let prepared =
+ tokio::task::spawn_blocking(move || prepare(copy, old, previous, target, own)).await;
let (old, metadata, plan, own_missing, had_history) = match prepared {
Ok(Prepared::Ready {
@@ -395,7 +401,15 @@ async fn finish<H: Host>(host: &H) {
}
/// Verifies the synced document and decides about the old document's own changes.
-fn prepare(mut copy: AutoCommit, mut old: AutoCommit, previous: Epoch, target: Epoch) -> Prepared {
+/// `own`: this node's actors (`RemakeState::own_actors`); the old document's own actor
+/// counts in any case.
+fn prepare(
+ mut copy: AutoCommit,
+ mut old: AutoCommit,
+ previous: Epoch,
+ target: Epoch,
+ mut own: Vec<ActorId>,
+) -> Prepared {
if copy.get_change_by_hash(&ChangeHash(target.id)).is_none() {
return Prepared::NotYet(old);
}
@@ -421,7 +435,7 @@ fn prepare(mut copy: AutoCommit, mut old: AutoCommit, previous: Epoch, target: E
.ok()
.filter(|next| next.previous == previous);
- let own = old.get_actor().clone();
+ own.push(old.get_actor().clone());
let clock = next
.as_ref()
.map_or_else(BTreeMap::new, |next| next.clock.clone());
@@ -573,7 +587,7 @@ mod tests {
#[test]
fn replays_within_the_window() {
let (old, swarm, target) = scenario(&json!({}));
- match prepare(swarm, old, Epoch::GENESIS, target) {
+ match prepare(swarm, old, Epoch::GENESIS, target, Vec::new()) {
Prepared::Ready {
plan: Plan::Replay(paths, _),
own_missing,
@@ -589,7 +603,7 @@ mod tests {
#[test]
fn quarantines_outside_the_window() {
let (old, swarm, target) = scenario(&json!({ "replayWindow": { "epochs": 0 } }));
- match prepare(swarm, old, Epoch::GENESIS, target) {
+ match prepare(swarm, old, Epoch::GENESIS, target, Vec::new()) {
Prepared::Ready {
plan: Plan::Quarantine { paths, .. },
..
@@ -602,7 +616,7 @@ mod tests {
fn new_node_has_nothing_to_replay() {
let (_, swarm, target) = scenario(&json!({}));
assert!(matches!(
- prepare(swarm, AutoCommit::new(), Epoch::GENESIS, target),
+ prepare(swarm, AutoCommit::new(), Epoch::GENESIS, target, Vec::new()),
Prepared::Ready {
plan: Plan::Nothing,
had_history: false,
@@ -615,7 +629,7 @@ mod tests {
fn waits_for_the_target_epoch() {
let (old, _, target) = scenario(&json!({}));
assert!(matches!(
- prepare(AutoCommit::new(), old, Epoch::GENESIS, target),
+ prepare(AutoCommit::new(), old, Epoch::GENESIS, target, Vec::new()),
Prepared::NotYet(_)
));
}