mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-30 22:34:13 +00:00
Merge pull request #787 from zed-industries/buffer-divergence
Fix divergence bug when peer reconnects reusing a prior replica id
This commit is contained in:
commit
28f44a3252
2 changed files with 54 additions and 7 deletions
|
@ -821,7 +821,10 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
|
||||||
}
|
}
|
||||||
50..=59 if replica_ids.len() < max_peers => {
|
50..=59 if replica_ids.len() < max_peers => {
|
||||||
let old_buffer = buffer.read(cx).to_proto();
|
let old_buffer = buffer.read(cx).to_proto();
|
||||||
let new_replica_id = replica_ids.len() as ReplicaId;
|
let new_replica_id = (0..=replica_ids.len() as ReplicaId)
|
||||||
|
.filter(|replica_id| *replica_id != buffer.read(cx).replica_id())
|
||||||
|
.choose(&mut rng)
|
||||||
|
.unwrap();
|
||||||
log::info!(
|
log::info!(
|
||||||
"Adding new replica {} (replicating from {})",
|
"Adding new replica {} (replicating from {})",
|
||||||
new_replica_id,
|
new_replica_id,
|
||||||
|
@ -830,6 +833,11 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
|
||||||
new_buffer = Some(cx.add_model(|cx| {
|
new_buffer = Some(cx.add_model(|cx| {
|
||||||
let mut new_buffer =
|
let mut new_buffer =
|
||||||
Buffer::from_proto(new_replica_id, old_buffer, None, cx).unwrap();
|
Buffer::from_proto(new_replica_id, old_buffer, None, cx).unwrap();
|
||||||
|
log::info!(
|
||||||
|
"New replica {} text: {:?}",
|
||||||
|
new_buffer.replica_id(),
|
||||||
|
new_buffer.text()
|
||||||
|
);
|
||||||
new_buffer.set_group_interval(Duration::from_millis(rng.gen_range(0..=200)));
|
new_buffer.set_group_interval(Duration::from_millis(rng.gen_range(0..=200)));
|
||||||
let network = network.clone();
|
let network = network.clone();
|
||||||
cx.subscribe(&cx.handle(), move |buffer, _, event, _| {
|
cx.subscribe(&cx.handle(), move |buffer, _, event, _| {
|
||||||
|
@ -843,8 +851,33 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
|
||||||
.detach();
|
.detach();
|
||||||
new_buffer
|
new_buffer
|
||||||
}));
|
}));
|
||||||
replica_ids.push(new_replica_id);
|
|
||||||
network.borrow_mut().replicate(replica_id, new_replica_id);
|
network.borrow_mut().replicate(replica_id, new_replica_id);
|
||||||
|
|
||||||
|
if new_replica_id as usize == replica_ids.len() {
|
||||||
|
replica_ids.push(new_replica_id);
|
||||||
|
} else {
|
||||||
|
let new_buffer = new_buffer.take().unwrap();
|
||||||
|
while network.borrow().has_unreceived(new_replica_id) {
|
||||||
|
let ops = network
|
||||||
|
.borrow_mut()
|
||||||
|
.receive(new_replica_id)
|
||||||
|
.into_iter()
|
||||||
|
.map(|op| proto::deserialize_operation(op).unwrap());
|
||||||
|
if ops.len() > 0 {
|
||||||
|
log::info!(
|
||||||
|
"peer {} (version: {:?}) applying {} ops from the network. {:?}",
|
||||||
|
new_replica_id,
|
||||||
|
buffer.read(cx).version(),
|
||||||
|
ops.len(),
|
||||||
|
ops
|
||||||
|
);
|
||||||
|
new_buffer.update(cx, |new_buffer, cx| {
|
||||||
|
new_buffer.apply_ops(ops, cx).unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffers[new_replica_id as usize] = new_buffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
60..=69 if mutation_count != 0 => {
|
60..=69 if mutation_count != 0 => {
|
||||||
buffer.update(cx, |buffer, cx| {
|
buffer.update(cx, |buffer, cx| {
|
||||||
|
@ -861,9 +894,11 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
|
||||||
.map(|op| proto::deserialize_operation(op).unwrap());
|
.map(|op| proto::deserialize_operation(op).unwrap());
|
||||||
if ops.len() > 0 {
|
if ops.len() > 0 {
|
||||||
log::info!(
|
log::info!(
|
||||||
"peer {} applying {} ops from the network.",
|
"peer {} (version: {:?}) applying {} ops from the network. {:?}",
|
||||||
replica_id,
|
replica_id,
|
||||||
ops.len()
|
buffer.read(cx).version(),
|
||||||
|
ops.len(),
|
||||||
|
ops
|
||||||
);
|
);
|
||||||
buffer.update(cx, |buffer, cx| buffer.apply_ops(ops, cx).unwrap());
|
buffer.update(cx, |buffer, cx| buffer.apply_ops(ops, cx).unwrap());
|
||||||
}
|
}
|
||||||
|
@ -886,6 +921,12 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
|
||||||
let first_buffer = buffers[0].read(cx).snapshot();
|
let first_buffer = buffers[0].read(cx).snapshot();
|
||||||
for buffer in &buffers[1..] {
|
for buffer in &buffers[1..] {
|
||||||
let buffer = buffer.read(cx).snapshot();
|
let buffer = buffer.read(cx).snapshot();
|
||||||
|
assert_eq!(
|
||||||
|
buffer.version(),
|
||||||
|
first_buffer.version(),
|
||||||
|
"Replica {} version != Replica 0 version",
|
||||||
|
buffer.replica_id()
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
buffer.text(),
|
buffer.text(),
|
||||||
first_buffer.text(),
|
first_buffer.text(),
|
||||||
|
@ -915,7 +956,12 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
|
||||||
.filter(|(replica_id, _)| **replica_id != buffer.replica_id())
|
.filter(|(replica_id, _)| **replica_id != buffer.replica_id())
|
||||||
.map(|(replica_id, selections)| (*replica_id, selections.iter().collect::<Vec<_>>()))
|
.map(|(replica_id, selections)| (*replica_id, selections.iter().collect::<Vec<_>>()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
assert_eq!(actual_remote_selections, expected_remote_selections);
|
assert_eq!(
|
||||||
|
actual_remote_selections,
|
||||||
|
expected_remote_selections,
|
||||||
|
"Replica {} remote selections != expected selections",
|
||||||
|
buffer.replica_id()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -826,6 +826,8 @@ impl Buffer {
|
||||||
edit.timestamp,
|
edit.timestamp,
|
||||||
);
|
);
|
||||||
self.snapshot.version.observe(edit.timestamp.local());
|
self.snapshot.version.observe(edit.timestamp.local());
|
||||||
|
self.local_clock.observe(edit.timestamp.local());
|
||||||
|
self.lamport_clock.observe(edit.timestamp.lamport());
|
||||||
self.resolve_edit(edit.timestamp.local());
|
self.resolve_edit(edit.timestamp.local());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -836,6 +838,7 @@ impl Buffer {
|
||||||
if !self.version.observed(undo.id) {
|
if !self.version.observed(undo.id) {
|
||||||
self.apply_undo(&undo)?;
|
self.apply_undo(&undo)?;
|
||||||
self.snapshot.version.observe(undo.id);
|
self.snapshot.version.observe(undo.id);
|
||||||
|
self.local_clock.observe(undo.id);
|
||||||
self.lamport_clock.observe(lamport_timestamp);
|
self.lamport_clock.observe(lamport_timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1033,8 +1036,6 @@ impl Buffer {
|
||||||
self.snapshot.visible_text = visible_text;
|
self.snapshot.visible_text = visible_text;
|
||||||
self.snapshot.deleted_text = deleted_text;
|
self.snapshot.deleted_text = deleted_text;
|
||||||
self.snapshot.insertions.edit(new_insertions, &());
|
self.snapshot.insertions.edit(new_insertions, &());
|
||||||
self.local_clock.observe(timestamp.local());
|
|
||||||
self.lamport_clock.observe(timestamp.lamport());
|
|
||||||
self.subscriptions.publish_mut(&edits);
|
self.subscriptions.publish_mut(&edits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue