send revsion in sequence

This commit is contained in:
appflowy
2021-10-07 20:46:29 +08:00
parent f84fb6f87f
commit 97ac22ec02
12 changed files with 316 additions and 213 deletions

View File

@ -48,8 +48,6 @@ impl ServerEditDoc {
})
}
pub fn document_json(&self) -> String { self.document.read().to_json() }
#[tracing::instrument(
level = "debug",
skip(self, user),
@ -64,14 +62,14 @@ impl ServerEditDoc {
match cur_rev_id.cmp(&rev_id) {
Ordering::Less => {
user.socket
.do_send(mk_pull_rev_ws_message(&self.doc_id, next(cur_rev_id), rev_id))
.do_send(mk_pull_message(&self.doc_id, next(cur_rev_id), rev_id))
.map_err(internal_error)?;
},
Ordering::Equal => {},
Ordering::Greater => {
let doc_delta = self.document.read().delta().clone();
let cli_revision = self.mk_revision(rev_id, doc_delta);
let ws_cli_revision = mk_push_rev_ws_message(&self.doc_id, cli_revision);
let ws_cli_revision = mk_push_message(&self.doc_id, cli_revision);
user.socket.do_send(ws_cli_revision).map_err(internal_error)?;
},
}
@ -94,38 +92,42 @@ impl ServerEditDoc {
revision: Revision,
pg_pool: Data<PgPool>,
) -> Result<(), ServerError> {
// Opti: find out another way to keep the user socket available.
self.users.insert(user.id(), user.clone());
let cur_rev_id = self.rev_id.load(SeqCst);
match cur_rev_id.cmp(&revision.rev_id) {
Ordering::Less => {
let next_rev_id = next(cur_rev_id);
if next_rev_id == revision.base_rev_id || cur_rev_id == revision.base_rev_id {
if cur_rev_id == revision.base_rev_id || next_rev_id == revision.base_rev_id {
// The rev is in the right order, just compose it.
let _ = self.compose_revision(&revision, pg_pool).await?;
user.socket
.do_send(mk_acked_ws_message(&revision))
.do_send(mk_acked_message(&revision))
.map_err(internal_error)?;
} else {
// The server document is outdated, pull the missing revision from the client.
user.socket
.do_send(mk_pull_message(&self.doc_id, next_rev_id, revision.rev_id))
.map_err(internal_error)?;
}
// The server document is outdated, try to get the missing revision from the
// client.
user.socket
.do_send(mk_pull_rev_ws_message(&self.doc_id, next_rev_id, revision.rev_id))
.map_err(internal_error)?;
},
Ordering::Equal => {},
Ordering::Equal => {
// Do nothing
},
Ordering::Greater => {
// The client document is outdated. Transform the client revision delta and then
// send the prime delta to the client. Client should compose the this prime
// delta.
let cli_revision = self.transform_revision(&revision)?;
let ws_cli_revision = mk_push_rev_ws_message(&self.doc_id, cli_revision);
user.socket.do_send(ws_cli_revision).map_err(internal_error)?;
user.socket
.do_send(mk_push_message(&self.doc_id, cli_revision))
.map_err(internal_error)?;
},
}
Ok(())
}
pub fn document_json(&self) -> String { self.document.read().to_json() }
async fn compose_revision(&self, revision: &Revision, pg_pool: Data<PgPool>) -> Result<(), ServerError> {
let delta = Delta::from_bytes(&revision.delta_data).map_err(internal_error)?;
let _ = self.compose_delta(delta)?;
@ -197,7 +199,7 @@ impl ServerEditDoc {
}
}
fn mk_push_rev_ws_message(doc_id: &str, revision: Revision) -> WsMessageAdaptor {
fn mk_push_message(doc_id: &str, revision: Revision) -> WsMessageAdaptor {
let bytes = revision.write_to_bytes().unwrap();
let data = WsDocumentData {
doc_id: doc_id.to_string(),
@ -207,7 +209,7 @@ fn mk_push_rev_ws_message(doc_id: &str, revision: Revision) -> WsMessageAdaptor
mk_ws_message(data)
}
fn mk_pull_rev_ws_message(doc_id: &str, from_rev_id: i64, to_rev_id: i64) -> WsMessageAdaptor {
fn mk_pull_message(doc_id: &str, from_rev_id: i64, to_rev_id: i64) -> WsMessageAdaptor {
let range = RevisionRange {
doc_id: doc_id.to_string(),
start: from_rev_id,
@ -224,7 +226,7 @@ fn mk_pull_rev_ws_message(doc_id: &str, from_rev_id: i64, to_rev_id: i64) -> WsM
mk_ws_message(data)
}
fn mk_acked_ws_message(revision: &Revision) -> WsMessageAdaptor {
fn mk_acked_message(revision: &Revision) -> WsMessageAdaptor {
// let mut wtr = vec![];
// let _ = wtr.write_i64::<BigEndian>(revision.rev_id);

View File

@ -30,6 +30,20 @@ async fn delta_sync_while_editing() {
.await;
}
#[actix_rt::test]
async fn delta_sync_multi_revs() {
let test = DocumentTest::new().await;
test.run_scripts(vec![
DocScript::ConnectWs,
DocScript::OpenDoc,
DocScript::InsertText(0, "abc"),
DocScript::InsertText(3, "123"),
DocScript::InsertText(6, "efg"),
DocScript::InsertText(9, "456"),
])
.await;
}
#[actix_rt::test]
async fn delta_sync_while_editing_with_attribute() {
let test = DocumentTest::new().await;