rename files

This commit is contained in:
appflowy
2021-10-05 11:46:56 +08:00
parent d0111e30dc
commit ad5bc23296
30 changed files with 176 additions and 137 deletions

View File

@ -8,7 +8,7 @@ use flowy_document::protobuf::{Doc, Revision};
use flowy_net::errors::{internal_error, Result as DocResult, ServerError};
use futures::stream::StreamExt;
use sqlx::PgPool;
use std::sync::Arc;
use std::sync::{atomic::Ordering::SeqCst, Arc};
use tokio::{
sync::{mpsc, oneshot},
task::spawn_blocking,
@ -35,6 +35,9 @@ pub enum EditMsg {
DocumentJson {
ret: oneshot::Sender<DocResult<String>>,
},
DocumentRevId {
ret: oneshot::Sender<DocResult<i64>>,
},
NewDocUser {
user: Arc<WsUser>,
socket: Socket,
@ -97,6 +100,10 @@ impl EditDocActor {
.map_err(internal_error);
let _ = ret.send(json);
},
EditMsg::DocumentRevId { ret } => {
let edit_context = self.edit_doc.clone();
let _ = ret.send(Ok(edit_context.rev_id.load(SeqCst)));
},
EditMsg::NewDocUser {
user,
socket,

View File

@ -32,8 +32,8 @@ use std::{
};
pub struct ServerEditDoc {
doc_id: String,
rev_id: AtomicI64,
pub doc_id: String,
pub rev_id: AtomicI64,
document: Arc<RwLock<Document>>,
users: DashMap<String, EditUser>,
}
@ -121,7 +121,7 @@ impl ServerEditDoc {
// 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_client_revision(&revision)?;
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)?;
},
@ -137,8 +137,16 @@ impl ServerEditDoc {
Ok(())
}
fn transform_client_revision(&self, revision: &Revision) -> Result<Revision, ServerError> {
let (cli_prime, server_prime) = self.transform(&revision.delta_data).map_err(internal_error)?;
#[tracing::instrument(level = "debug", skip(self, revision))]
fn transform_revision(&self, revision: &Revision) -> Result<Revision, ServerError> {
let cli_delta = Delta::from_bytes(&revision.delta_data).map_err(internal_error)?;
let (cli_prime, server_prime) = self
.document
.read()
.delta()
.transform(&cli_delta)
.map_err(internal_error)?;
let _ = self.compose_delta(server_prime)?;
let cli_revision = self.mk_revision(revision.rev_id, cli_prime);
Ok(cli_revision)
@ -159,19 +167,14 @@ impl ServerEditDoc {
revision
}
#[tracing::instrument(level = "debug", skip(self, delta_data))]
fn transform(&self, delta_data: &Vec<u8>) -> Result<(Delta, Delta), OTError> {
log::debug!("Document: {}", self.document.read().to_json());
let doc_delta = self.document.read().delta().clone();
let cli_delta = Delta::from_bytes(delta_data)?;
log::debug!("Compose delta: {}", cli_delta);
let (cli_prime, server_prime) = doc_delta.transform(&cli_delta)?;
Ok((cli_prime, server_prime))
}
#[tracing::instrument(level = "debug", skip(self), err)]
#[tracing::instrument(
level = "debug",
skip(self, delta),
fields(
delta = %delta.to_json(),
result,
)
)]
fn compose_delta(&self, delta: Delta) -> Result<(), ServerError> {
// Opti: push each revision into queue and process it one by one.
match self.document.try_write_for(Duration::from_millis(300)) {
@ -180,7 +183,7 @@ impl ServerEditDoc {
},
Some(mut write_guard) => {
let _ = write_guard.compose_delta(&delta).map_err(internal_error)?;
log::debug!("Document: {}", write_guard.to_json());
tracing::Span::current().record("result", &write_guard.to_json().as_str());
},
}
Ok(())

View File

@ -18,7 +18,6 @@ impl DocHandle {
let (sender, receiver) = mpsc::channel(100);
let actor = EditDocActor::new(receiver, doc, pg_pool)?;
tokio::task::spawn(actor.run());
Ok(Self { sender })
}
@ -58,6 +57,12 @@ impl DocHandle {
self.send(msg, rx).await?
}
pub async fn rev_id(&self) -> DocResult<i64> {
let (ret, rx) = oneshot::channel();
let msg = EditMsg::DocumentRevId { ret };
self.send(msg, rx).await?
}
pub(crate) async fn send<T>(&self, msg: EditMsg, rx: oneshot::Receiver<T>) -> DocResult<T> {
let _ = self.sender.send(msg).await.map_err(internal_error)?;
let result = rx.await?;

View File

@ -1,5 +1,6 @@
use crate::document::helper::{DocScript, DocumentTest};
use flowy_document::services::doc::{Document, FlowyDoc};
use flowy_ot::core::{Attribute, Interval};
#[rustfmt::skip]
// ┌─────────┐ ┌─────────┐
@ -16,15 +17,33 @@ use flowy_document::services::doc::{Document, FlowyDoc};
// └──────────────────────────┘ │ │ └──────────────────────┘
// │ │
#[actix_rt::test]
async fn delta_sync_after_ws_connection() {
async fn delta_sync_while_editing() {
let test = DocumentTest::new().await;
test.run_scripts(vec![
DocScript::ConnectWs,
DocScript::OpenDoc,
DocScript::SendText(0, "abc"),
DocScript::SendText(3, "123"),
DocScript::InsertText(0, "abc"),
DocScript::InsertText(3, "123"),
DocScript::AssertClient(r#"[{"insert":"abc123\n"}]"#),
DocScript::AssertServer(r#"[{"insert":"abc123\n"}]"#),
DocScript::AssertServer(r#"[{"insert":"abc123\n"}]"#, 2),
])
.await;
}
#[actix_rt::test]
async fn delta_sync_while_editing_with_attribute() {
let test = DocumentTest::new().await;
test.run_scripts(vec![
DocScript::ConnectWs,
DocScript::OpenDoc,
DocScript::InsertText(0, "abc"),
DocScript::FormatText(Interval::new(0, 3), Attribute::Bold(true)),
DocScript::AssertClient(r#"[{"insert":"abc","attributes":{"bold":true}},{"insert":"\n"}]"#),
DocScript::AssertServer(r#"[{"insert":"abc","attributes":{"bold":true}},{"insert":"\n"}]"#, 2),
DocScript::InsertText(3, "efg"),
DocScript::FormatText(Interval::new(3, 5), Attribute::Italic(true)),
DocScript::AssertClient(r#"[{"insert":"abc","attributes":{"bold":true}},{"insert":"ef","attributes":{"bold":true,"italic":true}},{"insert":"g","attributes":{"bold":true}},{"insert":"\n"}]"#),
DocScript::AssertServer(r#"[{"insert":"abc","attributes":{"bold":true}},{"insert":"ef","attributes":{"bold":true,"italic":true}},{"insert":"g","attributes":{"bold":true}},{"insert":"\n"}]"#, 4),
])
.await;
}
@ -54,7 +73,7 @@ async fn delta_sync_with_http_request() {
DocScript::SetServerDocument(json, 3),
DocScript::OpenDoc,
DocScript::AssertClient(r#"[{"insert":"123456\n"}]"#),
DocScript::AssertServer(r#"[{"insert":"123456\n"}]"#),
DocScript::AssertServer(r#"[{"insert":"123456\n"}]"#, 3),
])
.await;
}
@ -116,10 +135,10 @@ async fn delta_sync_while_local_rev_less_than_server_rev() {
test.run_scripts(vec![
DocScript::OpenDoc,
DocScript::SetServerDocument(json, 3),
DocScript::SendText(0, "abc"),
DocScript::InsertText(0, "abc"),
DocScript::ConnectWs,
DocScript::AssertClient(r#"[{"insert":"abc\n123\n"}]"#),
DocScript::AssertServer(r#"[{"insert":"abc\n123\n"}]"#),
DocScript::AssertServer(r#"[{"insert":"abc\n123\n"}]"#, 4),
])
.await;
}
@ -160,11 +179,11 @@ async fn delta_sync_while_local_rev_greater_than_server_rev() {
DocScript::SetServerDocument(json, 1),
DocScript::OpenDoc,
DocScript::AssertClient(r#"[{"insert":"123\n"}]"#),
DocScript::SendText(3, "abc"),
DocScript::SendText(6, "efg"),
DocScript::InsertText(3, "abc"),
DocScript::InsertText(6, "efg"),
DocScript::ConnectWs,
DocScript::AssertClient(r#"[{"insert":"123abcefg\n"}]"#),
DocScript::AssertServer(r#"[{"insert":"123abcefg\n"}]"#),
DocScript::AssertServer(r#"[{"insert":"123abcefg\n"}]"#, 3),
])
.await;
}

View File

@ -15,6 +15,7 @@ use flowy_user::services::user::UserSession;
use crate::helper::{spawn_server, TestServer};
use flowy_document::protobuf::UpdateDocParams;
use flowy_ot::core::{Attribute, Interval};
use parking_lot::RwLock;
use serde::__private::Formatter;
@ -25,27 +26,14 @@ pub struct DocumentTest {
#[derive(Clone)]
pub enum DocScript {
ConnectWs,
SendText(usize, &'static str),
InsertText(usize, &'static str),
FormatText(Interval, Attribute),
AssertClient(&'static str),
AssertServer(&'static str),
AssertServer(&'static str, i64),
SetServerDocument(String, i64), // delta_json, rev_id
OpenDoc,
}
impl std::fmt::Display for DocScript {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let name = match self {
DocScript::ConnectWs => "ConnectWs",
DocScript::SendText(_, _) => "SendText",
DocScript::AssertClient(_) => "AssertClient",
DocScript::AssertServer(_) => "AssertServer",
DocScript::SetServerDocument(_, _) => "SetServerDocument",
DocScript::OpenDoc => "OpenDoc",
};
f.write_str(&format!("******** {} *********", name))
}
}
impl DocumentTest {
pub async fn new() -> Self {
let server = spawn_server().await;
@ -122,19 +110,28 @@ async fn run_scripts(context: Arc<RwLock<ScriptContext>>, scripts: Vec<DocScript
DocScript::OpenDoc => {
context.write().open_doc().await;
},
DocScript::SendText(index, s) => {
DocScript::InsertText(index, s) => {
context.read().client_edit_context().insert(index, s).await.unwrap();
},
DocScript::FormatText(interval, attribute) => {
context
.read()
.client_edit_context()
.format(interval, attribute)
.await
.unwrap();
},
DocScript::AssertClient(s) => {
sleep(Duration::from_millis(100)).await;
let json = context.read().client_edit_context().doc_json().await.unwrap();
assert_eq(s, &json);
},
DocScript::AssertServer(s) => {
DocScript::AssertServer(s, rev_id) => {
sleep(Duration::from_millis(100)).await;
let pg_pool = context.read().pool.clone();
let doc_manager = context.read().doc_manager.clone();
let edit_doc = doc_manager.get(&doc_id, pg_pool).await.unwrap().unwrap();
assert_eq!(edit_doc.rev_id().await.unwrap(), rev_id);
let json = edit_doc.document_json().await.unwrap();
assert_eq(s, &json);
},