Stream buffer ops in the background when creating buffer for peers

This commit is contained in:
Antonio Scandurra
2022-08-23 16:05:56 +02:00
parent ec48ffc9da
commit 954695f5fe
6 changed files with 209 additions and 98 deletions
+5 -13
View File
@@ -359,9 +359,8 @@ impl Buffer {
pub fn from_proto(
replica_id: ReplicaId,
message: proto::Buffer,
message: proto::BufferState,
file: Option<Arc<dyn File>>,
cx: &mut ModelContext<Self>,
) -> Result<Self> {
let buffer = TextBuffer::new(replica_id, message.id, message.base_text);
let mut this = Self::build(buffer, file);
@@ -369,17 +368,10 @@ impl Buffer {
proto::LineEnding::from_i32(message.line_ending)
.ok_or_else(|| anyhow!("missing line_ending"))?,
));
let ops = message
.operations
.into_iter()
.map(proto::deserialize_operation)
.collect::<Result<Vec<_>>>()?;
this.apply_ops(ops, cx)?;
Ok(this)
}
pub fn to_proto(&self) -> proto::Buffer {
pub fn to_proto(&self) -> (proto::BufferState, Vec<proto::Operation>) {
let mut operations = self
.text
.history()
@@ -406,13 +398,13 @@ impl Buffer {
)))
.collect::<Vec<_>>();
operations.sort_unstable_by_key(proto::lamport_timestamp_for_operation);
proto::Buffer {
let state = proto::BufferState {
id: self.remote_id(),
file: self.file.as_ref().map(|f| f.to_proto()),
base_text: self.base_text().to_string(),
operations,
line_ending: proto::serialize_line_ending(self.line_ending()) as i32,
}
};
(state, operations)
}
pub fn with_language(mut self, language: Arc<Language>, cx: &mut ModelContext<Self>) -> Self {
+46 -43
View File
@@ -1,6 +1,5 @@
use crate::{
diagnostic_set::DiagnosticEntry, CodeAction, CodeLabel, Completion, Diagnostic, Language,
Operation,
};
use anyhow::{anyhow, Result};
use clock::ReplicaId;
@@ -9,7 +8,7 @@ use rpc::proto;
use std::{ops::Range, sync::Arc};
use text::*;
pub use proto::{Buffer, LineEnding, SelectionSet};
pub use proto::{BufferState, LineEnding, Operation, SelectionSet};
pub fn deserialize_line_ending(message: proto::LineEnding) -> text::LineEnding {
match message {
@@ -25,13 +24,13 @@ pub fn serialize_line_ending(message: text::LineEnding) -> proto::LineEnding {
}
}
pub fn serialize_operation(operation: &Operation) -> proto::Operation {
pub fn serialize_operation(operation: &crate::Operation) -> proto::Operation {
proto::Operation {
variant: Some(match operation {
Operation::Buffer(text::Operation::Edit(edit)) => {
crate::Operation::Buffer(text::Operation::Edit(edit)) => {
proto::operation::Variant::Edit(serialize_edit_operation(edit))
}
Operation::Buffer(text::Operation::Undo {
crate::Operation::Buffer(text::Operation::Undo {
undo,
lamport_timestamp,
}) => proto::operation::Variant::Undo(proto::operation::Undo {
@@ -49,7 +48,7 @@ pub fn serialize_operation(operation: &Operation) -> proto::Operation {
})
.collect(),
}),
Operation::UpdateSelections {
crate::Operation::UpdateSelections {
selections,
line_mode,
lamport_timestamp,
@@ -59,7 +58,7 @@ pub fn serialize_operation(operation: &Operation) -> proto::Operation {
selections: serialize_selections(selections),
line_mode: *line_mode,
}),
Operation::UpdateDiagnostics {
crate::Operation::UpdateDiagnostics {
diagnostics,
lamport_timestamp,
} => proto::operation::Variant::UpdateDiagnostics(proto::UpdateDiagnostics {
@@ -67,7 +66,7 @@ pub fn serialize_operation(operation: &Operation) -> proto::Operation {
lamport_timestamp: lamport_timestamp.value,
diagnostics: serialize_diagnostics(diagnostics.iter()),
}),
Operation::UpdateCompletionTriggers {
crate::Operation::UpdateCompletionTriggers {
triggers,
lamport_timestamp,
} => proto::operation::Variant::UpdateCompletionTriggers(
@@ -165,41 +164,43 @@ pub fn serialize_anchor(anchor: &Anchor) -> proto::Anchor {
}
}
pub fn deserialize_operation(message: proto::Operation) -> Result<Operation> {
pub fn deserialize_operation(message: proto::Operation) -> Result<crate::Operation> {
Ok(
match message
.variant
.ok_or_else(|| anyhow!("missing operation variant"))?
{
proto::operation::Variant::Edit(edit) => {
Operation::Buffer(text::Operation::Edit(deserialize_edit_operation(edit)))
crate::Operation::Buffer(text::Operation::Edit(deserialize_edit_operation(edit)))
}
proto::operation::Variant::Undo(undo) => Operation::Buffer(text::Operation::Undo {
lamport_timestamp: clock::Lamport {
replica_id: undo.replica_id as ReplicaId,
value: undo.lamport_timestamp,
},
undo: UndoOperation {
id: clock::Local {
proto::operation::Variant::Undo(undo) => {
crate::Operation::Buffer(text::Operation::Undo {
lamport_timestamp: clock::Lamport {
replica_id: undo.replica_id as ReplicaId,
value: undo.local_timestamp,
value: undo.lamport_timestamp,
},
version: deserialize_version(undo.version),
counts: undo
.counts
.into_iter()
.map(|c| {
(
clock::Local {
replica_id: c.replica_id as ReplicaId,
value: c.local_timestamp,
},
c.count,
)
})
.collect(),
},
}),
undo: UndoOperation {
id: clock::Local {
replica_id: undo.replica_id as ReplicaId,
value: undo.local_timestamp,
},
version: deserialize_version(undo.version),
counts: undo
.counts
.into_iter()
.map(|c| {
(
clock::Local {
replica_id: c.replica_id as ReplicaId,
value: c.local_timestamp,
},
c.count,
)
})
.collect(),
},
})
}
proto::operation::Variant::UpdateSelections(message) => {
let selections = message
.selections
@@ -215,7 +216,7 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<Operation> {
})
.collect::<Vec<_>>();
Operation::UpdateSelections {
crate::Operation::UpdateSelections {
lamport_timestamp: clock::Lamport {
replica_id: message.replica_id as ReplicaId,
value: message.lamport_timestamp,
@@ -224,15 +225,17 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<Operation> {
line_mode: message.line_mode,
}
}
proto::operation::Variant::UpdateDiagnostics(message) => Operation::UpdateDiagnostics {
diagnostics: deserialize_diagnostics(message.diagnostics),
lamport_timestamp: clock::Lamport {
replica_id: message.replica_id as ReplicaId,
value: message.lamport_timestamp,
},
},
proto::operation::Variant::UpdateDiagnostics(message) => {
crate::Operation::UpdateDiagnostics {
diagnostics: deserialize_diagnostics(message.diagnostics),
lamport_timestamp: clock::Lamport {
replica_id: message.replica_id as ReplicaId,
value: message.lamport_timestamp,
},
}
}
proto::operation::Variant::UpdateCompletionTriggers(message) => {
Operation::UpdateCompletionTriggers {
crate::Operation::UpdateCompletionTriggers {
triggers: message.triggers,
lamport_timestamp: clock::Lamport {
replica_id: message.replica_id as ReplicaId,
+32 -7
View File
@@ -2,6 +2,7 @@ use super::*;
use clock::ReplicaId;
use collections::BTreeMap;
use gpui::{ModelHandle, MutableAppContext};
use proto::deserialize_operation;
use rand::prelude::*;
use settings::Settings;
use std::{
@@ -1047,8 +1048,18 @@ fn test_serialization(cx: &mut gpui::MutableAppContext) {
});
assert_eq!(buffer1.read(cx).text(), "abcDF");
let message = buffer1.read(cx).to_proto();
let buffer2 = cx.add_model(|cx| Buffer::from_proto(1, message, None, cx).unwrap());
let (state, ops) = buffer1.read(cx).to_proto();
let buffer2 = cx.add_model(|cx| {
let mut buffer = Buffer::from_proto(1, state, None).unwrap();
buffer
.apply_ops(
ops.into_iter()
.map(|op| proto::deserialize_operation(op).unwrap()),
cx,
)
.unwrap();
buffer
});
assert_eq!(buffer2.read(cx).text(), "abcDF");
}
@@ -1075,9 +1086,15 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
for i in 0..rng.gen_range(min_peers..=max_peers) {
let buffer = cx.add_model(|cx| {
let mut buffer =
Buffer::from_proto(i as ReplicaId, base_buffer.read(cx).to_proto(), None, cx)
.unwrap();
let (state, ops) = base_buffer.read(cx).to_proto();
let mut buffer = Buffer::from_proto(i as ReplicaId, state, None).unwrap();
buffer
.apply_ops(
ops.into_iter()
.map(|op| proto::deserialize_operation(op).unwrap()),
cx,
)
.unwrap();
buffer.set_group_interval(Duration::from_millis(rng.gen_range(0..=200)));
let network = network.clone();
cx.subscribe(&cx.handle(), move |buffer, _, event, _| {
@@ -1164,7 +1181,7 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
mutation_count -= 1;
}
50..=59 if replica_ids.len() < max_peers => {
let old_buffer = buffer.read(cx).to_proto();
let (old_buffer_state, old_buffer_ops) = buffer.read(cx).to_proto();
let new_replica_id = (0..=replica_ids.len() as ReplicaId)
.filter(|replica_id| *replica_id != buffer.read(cx).replica_id())
.choose(&mut rng)
@@ -1176,7 +1193,15 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
);
new_buffer = Some(cx.add_model(|cx| {
let mut new_buffer =
Buffer::from_proto(new_replica_id, old_buffer, None, cx).unwrap();
Buffer::from_proto(new_replica_id, old_buffer_state, None).unwrap();
new_buffer
.apply_ops(
old_buffer_ops
.into_iter()
.map(|op| deserialize_operation(op).unwrap()),
cx,
)
.unwrap();
log::info!(
"New replica {} text: {:?}",
new_buffer.replica_id(),