mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor flowy-collaboration directories
This commit is contained in:
@ -3,13 +3,12 @@ use crate::services::{
|
|||||||
persistence::{create_doc, read_doc},
|
persistence::{create_doc, read_doc},
|
||||||
ws_actor::{DocumentWebSocketActor, WSActorMessage},
|
ws_actor::{DocumentWebSocketActor, WSActorMessage},
|
||||||
},
|
},
|
||||||
web_socket::{WSClientData, WebSocketReceiver},
|
web_socket::{WebSocketReceiver, WSClientData},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::context::FlowyPersistence;
|
use crate::context::FlowyPersistence;
|
||||||
use backend_service::errors::ServerError;
|
use backend_service::errors::ServerError;
|
||||||
use flowy_collaboration::{
|
use flowy_collaboration::{
|
||||||
core::sync::{DocumentPersistence, ServerDocumentManager},
|
|
||||||
entities::{
|
entities::{
|
||||||
doc::{CreateDocParams, DocumentInfo},
|
doc::{CreateDocParams, DocumentInfo},
|
||||||
revision::{RepeatedRevision, Revision},
|
revision::{RepeatedRevision, Revision},
|
||||||
@ -25,6 +24,7 @@ use std::{
|
|||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
use flowy_collaboration::sync::{DocumentPersistence, ServerDocumentManager};
|
||||||
|
|
||||||
pub fn make_document_ws_receiver(persistence: Arc<FlowyPersistence>) -> Arc<DocumentWebSocketReceiver> {
|
pub fn make_document_ws_receiver(persistence: Arc<FlowyPersistence>) -> Arc<DocumentWebSocketReceiver> {
|
||||||
let document_persistence = Arc::new(DocumentPersistenceImpl(persistence.clone()));
|
let document_persistence = Arc::new(DocumentPersistenceImpl(persistence.clone()));
|
||||||
|
@ -7,13 +7,13 @@ use actix_rt::task::spawn_blocking;
|
|||||||
use crate::context::FlowyPersistence;
|
use crate::context::FlowyPersistence;
|
||||||
use async_stream::stream;
|
use async_stream::stream;
|
||||||
use backend_service::errors::{internal_error, Result, ServerError};
|
use backend_service::errors::{internal_error, Result, ServerError};
|
||||||
use flowy_collaboration::{
|
use flowy_collaboration::protobuf::{DocumentWSData, DocumentWSDataType, NewDocumentUser, Revision};
|
||||||
core::sync::{RevisionUser, ServerDocumentManager, SyncResponse},
|
|
||||||
protobuf::{DocumentWSData, DocumentWSDataType, NewDocumentUser, Revision},
|
|
||||||
};
|
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
|
|
||||||
use flowy_collaboration::protobuf::RepeatedRevision;
|
use flowy_collaboration::{
|
||||||
|
protobuf::RepeatedRevision,
|
||||||
|
sync::{RevisionUser, ServerDocumentManager, SyncResponse},
|
||||||
|
};
|
||||||
use std::{convert::TryInto, sync::Arc};
|
use std::{convert::TryInto, sync::Arc};
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ impl DocumentWebSocketActor {
|
|||||||
DocumentWSDataType::Ack => Ok(()),
|
DocumentWSDataType::Ack => Ok(()),
|
||||||
DocumentWSDataType::PushRev => self.handle_pushed_rev(user, document_data.data).await,
|
DocumentWSDataType::PushRev => self.handle_pushed_rev(user, document_data.data).await,
|
||||||
DocumentWSDataType::PullRev => Ok(()),
|
DocumentWSDataType::PullRev => Ok(()),
|
||||||
DocumentWSDataType::UserConnect => self.handle_user_connect(user, document_data).await,
|
DocumentWSDataType::UserConnect => Ok(()),
|
||||||
};
|
};
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {},
|
Ok(_) => {},
|
||||||
@ -105,18 +105,6 @@ impl DocumentWebSocketActor {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_user_connect(&self, user: Arc<ServerDocUser>, document_data: DocumentWSData) -> Result<()> {
|
|
||||||
let mut new_user = spawn_blocking(move || parse_from_bytes::<NewDocumentUser>(&document_data.data))
|
|
||||||
.await
|
|
||||||
.map_err(internal_error)??;
|
|
||||||
let repeated_revisions =
|
|
||||||
spawn_blocking(move || parse_from_bytes::<RepeatedRevision>(&new_user.take_revision_data()))
|
|
||||||
.await
|
|
||||||
.map_err(internal_error)??;
|
|
||||||
let _ = self.handle_revision(user, repeated_revisions).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_pushed_rev(&self, user: Arc<ServerDocUser>, data: Vec<u8>) -> Result<()> {
|
async fn handle_pushed_rev(&self, user: Arc<ServerDocUser>, data: Vec<u8>) -> Result<()> {
|
||||||
let repeated_revision = spawn_blocking(move || parse_from_bytes::<RepeatedRevision>(&data))
|
let repeated_revision = spawn_blocking(move || parse_from_bytes::<RepeatedRevision>(&data))
|
||||||
.await
|
.await
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::util::helper::{ViewTest, *};
|
use crate::util::helper::{ViewTest, *};
|
||||||
use flowy_collaboration::{
|
use flowy_collaboration::{
|
||||||
core::document::{Document, PlainDoc},
|
document::{Document, PlainDoc},
|
||||||
entities::{
|
entities::{
|
||||||
doc::{CreateDocParams, DocIdentifier},
|
doc::{CreateDocParams, DocIdentifier},
|
||||||
revision::{md5, RepeatedRevision, RevType, Revision},
|
revision::{md5, RepeatedRevision, RevType, Revision},
|
||||||
|
@ -4,7 +4,7 @@ use chrono::Utc;
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use flowy_collaboration::{core::document::default::initial_read_me, entities::doc::DocumentDelta};
|
use flowy_collaboration::{document::default::initial_read_me, entities::doc::DocumentDelta};
|
||||||
use flowy_core_data_model::user_default;
|
use flowy_core_data_model::user_default;
|
||||||
use flowy_net::entities::NetworkType;
|
use flowy_net::entities::NetworkType;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_collaboration::{
|
use flowy_collaboration::{
|
||||||
core::document::history::UndoResult,
|
document::history::UndoResult,
|
||||||
entities::{
|
entities::{
|
||||||
doc::DocumentDelta,
|
doc::DocumentDelta,
|
||||||
revision::{RevId, RevType, Revision},
|
revision::{RevId, RevType, Revision},
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use async_stream::stream;
|
use async_stream::stream;
|
||||||
|
|
||||||
use flowy_collaboration::{
|
use flowy_collaboration::{
|
||||||
core::document::{history::UndoResult, Document},
|
|
||||||
entities::revision::Revision,
|
entities::revision::Revision,
|
||||||
errors::CollaborateError,
|
errors::CollaborateError,
|
||||||
};
|
};
|
||||||
@ -13,6 +12,7 @@ use lib_ot::{
|
|||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::{mpsc, oneshot, RwLock};
|
use tokio::sync::{mpsc, oneshot, RwLock};
|
||||||
|
use flowy_collaboration::document::{Document, history::UndoResult};
|
||||||
|
|
||||||
pub(crate) struct EditorCommandQueue {
|
pub(crate) struct EditorCommandQueue {
|
||||||
doc_id: String,
|
doc_id: String,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use flowy_collaboration::{
|
use flowy_collaboration::{
|
||||||
core::document::default::initial_delta_string,
|
document::default::initial_delta_string,
|
||||||
entities::doc::{CreateDocParams, DocIdentifier, DocumentInfo, ResetDocumentParams},
|
entities::doc::{CreateDocParams, DocIdentifier, DocumentInfo, ResetDocumentParams},
|
||||||
};
|
};
|
||||||
use lib_infra::future::FutureResult;
|
use lib_infra::future::FutureResult;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![cfg_attr(rustfmt, rustfmt::skip)]
|
#![cfg_attr(rustfmt, rustfmt::skip)]
|
||||||
use crate::editor::{TestBuilder, TestOp::*};
|
use crate::editor::{TestBuilder, TestOp::*};
|
||||||
use flowy_collaboration::core::document::{FlowyDoc, PlainDoc};
|
use flowy_collaboration::document::{FlowyDoc, PlainDoc};
|
||||||
use lib_ot::core::{Interval, OperationTransformable, NEW_LINE, WHITESPACE, FlowyStr};
|
use lib_ot::core::{Interval, OperationTransformable, NEW_LINE, WHITESPACE, FlowyStr};
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
use lib_ot::rich_text::RichTextDelta;
|
use lib_ot::rich_text::RichTextDelta;
|
||||||
|
@ -5,7 +5,7 @@ mod serde_test;
|
|||||||
mod undo_redo_test;
|
mod undo_redo_test;
|
||||||
|
|
||||||
use derive_more::Display;
|
use derive_more::Display;
|
||||||
use flowy_collaboration::core::document::{CustomDocument, Document};
|
use flowy_collaboration::document::{CustomDocument, Document};
|
||||||
use lib_ot::{
|
use lib_ot::{
|
||||||
core::*,
|
core::*,
|
||||||
rich_text::{RichTextAttribute, RichTextAttributes, RichTextDelta},
|
rich_text::{RichTextAttribute, RichTextAttributes, RichTextDelta},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![allow(clippy::all)]
|
#![allow(clippy::all)]
|
||||||
use crate::editor::{Rng, TestBuilder, TestOp::*};
|
use crate::editor::{Rng, TestBuilder, TestOp::*};
|
||||||
use flowy_collaboration::core::document::{FlowyDoc, PlainDoc};
|
use flowy_collaboration::document::{FlowyDoc, PlainDoc};
|
||||||
use lib_ot::{
|
use lib_ot::{
|
||||||
core::*,
|
core::*,
|
||||||
rich_text::{AttributeBuilder, RichTextAttribute, RichTextAttributes, RichTextDelta},
|
rich_text::{AttributeBuilder, RichTextAttribute, RichTextAttributes, RichTextDelta},
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use flowy_collaboration::core::document::{Document, PlainDoc};
|
use flowy_collaboration::document::{Document, PlainDoc};
|
||||||
use lib_ot::{
|
use lib_ot::{
|
||||||
core::*,
|
core::*,
|
||||||
rich_text::{AttributeBuilder, RichTextAttribute, RichTextAttributeValue, RichTextDelta},
|
rich_text::{AttributeBuilder, RichTextAttribute, RichTextAttributeValue, RichTextDelta},
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::editor::{TestBuilder, TestOp::*};
|
use crate::editor::{TestBuilder, TestOp::*};
|
||||||
use flowy_collaboration::core::document::{FlowyDoc, PlainDoc, RECORD_THRESHOLD};
|
use flowy_collaboration::document::{FlowyDoc, PlainDoc, RECORD_THRESHOLD};
|
||||||
use lib_ot::core::{Interval, NEW_LINE, WHITESPACE};
|
use lib_ot::core::{Interval, NEW_LINE, WHITESPACE};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
pub mod document;
|
|
||||||
pub mod sync;
|
|
@ -1,5 +0,0 @@
|
|||||||
mod server_editor;
|
|
||||||
mod synchronizer;
|
|
||||||
|
|
||||||
pub use server_editor::*;
|
|
||||||
pub use synchronizer::*;
|
|
@ -8,13 +8,13 @@ pub fn initial_delta_string() -> String { initial_delta().to_json() }
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn initial_read_me() -> RichTextDelta {
|
pub fn initial_read_me() -> RichTextDelta {
|
||||||
let json = include_str!("./READ_ME.json");
|
let json = include_str!("READ_ME.json");
|
||||||
RichTextDelta::from_json(json).unwrap()
|
RichTextDelta::from_json(json).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::core::document::default::initial_read_me;
|
use crate::document::default::initial_read_me;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn load_read_me() {
|
fn load_read_me() {
|
@ -6,7 +6,7 @@ use lib_ot::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::document::{
|
document::{
|
||||||
default::initial_delta,
|
default::initial_delta,
|
||||||
history::{History, UndoResult},
|
history::{History, UndoResult},
|
||||||
view::{View, RECORD_THRESHOLD},
|
view::{View, RECORD_THRESHOLD},
|
@ -1,4 +1,4 @@
|
|||||||
use crate::core::document::DeleteExt;
|
use crate::document::DeleteExt;
|
||||||
use lib_ot::{
|
use lib_ot::{
|
||||||
core::{DeltaBuilder, Interval},
|
core::{DeltaBuilder, Interval},
|
||||||
rich_text::RichTextDelta,
|
rich_text::RichTextDelta,
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{core::document::DeleteExt, util::is_newline};
|
use crate::{document::DeleteExt, util::is_newline};
|
||||||
use lib_ot::{
|
use lib_ot::{
|
||||||
core::{Attributes, CharMetric, DeltaBuilder, DeltaIter, Interval, NEW_LINE},
|
core::{Attributes, CharMetric, DeltaBuilder, DeltaIter, Interval, NEW_LINE},
|
||||||
rich_text::{plain_attributes, RichTextDelta},
|
rich_text::{plain_attributes, RichTextDelta},
|
@ -4,7 +4,7 @@ use lib_ot::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::document::{extensions::helper::line_break, FormatExt},
|
document::{extensions::helper::line_break, FormatExt},
|
||||||
util::find_newline,
|
util::find_newline,
|
||||||
};
|
};
|
||||||
|
|
@ -4,7 +4,7 @@ use lib_ot::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::document::{extensions::helper::line_break, FormatExt},
|
document::{extensions::helper::line_break, FormatExt},
|
||||||
util::find_newline,
|
util::find_newline,
|
||||||
};
|
};
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{core::document::InsertExt, util::is_newline};
|
use crate::{document::InsertExt, util::is_newline};
|
||||||
use lib_ot::{
|
use lib_ot::{
|
||||||
core::{is_empty_line_at_index, DeltaBuilder, DeltaIter},
|
core::{is_empty_line_at_index, DeltaBuilder, DeltaIter},
|
||||||
rich_text::{attributes_except_header, RichTextAttributeKey, RichTextDelta},
|
rich_text::{attributes_except_header, RichTextAttributeKey, RichTextDelta},
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{core::document::InsertExt, util::is_whitespace};
|
use crate::{document::InsertExt, util::is_whitespace};
|
||||||
use lib_ot::{
|
use lib_ot::{
|
||||||
core::{count_utf16_code_units, DeltaBuilder, DeltaIter},
|
core::{count_utf16_code_units, DeltaBuilder, DeltaIter},
|
||||||
rich_text::{plain_attributes, RichTextAttribute, RichTextAttributes, RichTextDelta},
|
rich_text::{plain_attributes, RichTextAttribute, RichTextAttributes, RichTextDelta},
|
@ -1,4 +1,4 @@
|
|||||||
use crate::core::document::InsertExt;
|
use crate::document::InsertExt;
|
||||||
use lib_ot::{
|
use lib_ot::{
|
||||||
core::{Attributes, DeltaBuilder, DeltaIter, NEW_LINE},
|
core::{Attributes, DeltaBuilder, DeltaIter, NEW_LINE},
|
||||||
rich_text::{RichTextAttributeKey, RichTextAttributes, RichTextDelta},
|
rich_text::{RichTextAttributeKey, RichTextAttributes, RichTextDelta},
|
@ -1,4 +1,4 @@
|
|||||||
use crate::core::document::InsertExt;
|
use crate::document::InsertExt;
|
||||||
pub use auto_exit_block::*;
|
pub use auto_exit_block::*;
|
||||||
pub use auto_format::*;
|
pub use auto_format::*;
|
||||||
pub use default_insert::*;
|
pub use default_insert::*;
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{core::document::InsertExt, util::is_newline};
|
use crate::util::is_newline;
|
||||||
use lib_ot::{
|
use lib_ot::{
|
||||||
core::{DeltaBuilder, DeltaIter, NEW_LINE},
|
core::{DeltaBuilder, DeltaIter, NEW_LINE},
|
||||||
rich_text::{
|
rich_text::{
|
||||||
@ -10,6 +10,7 @@ use lib_ot::{
|
|||||||
RichTextDelta,
|
RichTextDelta,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use crate::document::InsertExt;
|
||||||
|
|
||||||
pub struct PreserveBlockFormatOnInsert {}
|
pub struct PreserveBlockFormatOnInsert {}
|
||||||
impl InsertExt for PreserveBlockFormatOnInsert {
|
impl InsertExt for PreserveBlockFormatOnInsert {
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
core::document::InsertExt,
|
document::InsertExt,
|
||||||
util::{contain_newline, is_newline},
|
util::{contain_newline, is_newline},
|
||||||
};
|
};
|
||||||
use lib_ot::{
|
use lib_ot::{
|
@ -1,8 +1,9 @@
|
|||||||
use crate::{core::document::InsertExt, util::is_newline};
|
use crate::util::is_newline;
|
||||||
use lib_ot::{
|
use lib_ot::{
|
||||||
core::{CharMetric, DeltaBuilder, DeltaIter, NEW_LINE},
|
core::{CharMetric, DeltaBuilder, DeltaIter, NEW_LINE},
|
||||||
rich_text::{RichTextAttributeKey, RichTextAttributes, RichTextDelta},
|
rich_text::{RichTextAttributeKey, RichTextAttributes, RichTextDelta},
|
||||||
};
|
};
|
||||||
|
use crate::document::InsertExt;
|
||||||
|
|
||||||
pub struct ResetLineFormatOnNewLine {}
|
pub struct ResetLineFormatOnNewLine {}
|
||||||
impl InsertExt for ResetLineFormatOnNewLine {
|
impl InsertExt for ResetLineFormatOnNewLine {
|
@ -1,4 +1,4 @@
|
|||||||
use crate::core::document::*;
|
use crate::document::*;
|
||||||
use lib_ot::{
|
use lib_ot::{
|
||||||
core::{trim, Interval},
|
core::{trim, Interval},
|
||||||
errors::{ErrorBuilder, OTError, OTErrorCode},
|
errors::{ErrorBuilder, OTError, OTErrorCode},
|
@ -1,4 +1,4 @@
|
|||||||
use crate::core::document::default::initial_delta;
|
use crate::document::default::initial_delta;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||||
use lib_ot::rich_text::RichTextDelta;
|
use lib_ot::rich_text::RichTextDelta;
|
||||||
|
@ -8,7 +8,7 @@ use std::convert::{TryFrom, TryInto};
|
|||||||
|
|
||||||
#[derive(Debug, Clone, ProtoBuf_Enum, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, ProtoBuf_Enum, Eq, PartialEq, Hash)]
|
||||||
pub enum DocumentWSDataType {
|
pub enum DocumentWSDataType {
|
||||||
// The frontend receives the Acked means the backend has accepted the revision
|
// The frontend receives the Ack means the backend has received the revision
|
||||||
Ack = 0,
|
Ack = 0,
|
||||||
// The frontend receives the PushRev event means the backend is pushing the new revision to frontend
|
// The frontend receives the PushRev event means the backend is pushing the new revision to frontend
|
||||||
PushRev = 1,
|
PushRev = 1,
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
pub mod core;
|
pub mod document;
|
||||||
pub mod entities;
|
pub mod entities;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod protobuf;
|
pub mod protobuf;
|
||||||
|
pub mod sync;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
pub use lib_ot::rich_text::RichTextDelta;
|
pub use lib_ot::rich_text::RichTextDelta;
|
||||||
|
@ -540,14 +540,6 @@ impl ::protobuf::reflect::ProtobufValue for NewDocumentUser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
|
||||||
pub enum DocumentWSDataType {
|
|
||||||
Ack = 0,
|
|
||||||
PushRev = 1,
|
|
||||||
PullRev = 2,
|
|
||||||
UserConnect = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::protobuf::ProtobufEnum for DocumentWSDataType {
|
impl ::protobuf::ProtobufEnum for DocumentWSDataType {
|
||||||
fn value(&self) -> i32 {
|
fn value(&self) -> i32 {
|
||||||
*self as i32
|
*self as i32
|
||||||
@ -581,6 +573,14 @@ impl ::protobuf::ProtobufEnum for DocumentWSDataType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
||||||
|
pub enum DocumentWSDataType {
|
||||||
|
Ack = 0,
|
||||||
|
PushRev = 1,
|
||||||
|
PullRev = 2,
|
||||||
|
UserConnect = 3,
|
||||||
|
}
|
||||||
|
|
||||||
impl ::std::marker::Copy for DocumentWSDataType {
|
impl ::std::marker::Copy for DocumentWSDataType {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
shared-lib/flowy-collaboration/src/sync/mod.rs
Normal file
5
shared-lib/flowy-collaboration/src/sync/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
mod server;
|
||||||
|
mod synchronizer;
|
||||||
|
|
||||||
|
pub use server::*;
|
||||||
|
pub use synchronizer::*;
|
@ -1,10 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
document::Document,
|
||||||
document::Document,
|
|
||||||
sync::{RevisionSynchronizer, RevisionUser},
|
|
||||||
},
|
|
||||||
entities::{doc::DocumentInfo, revision::Revision},
|
entities::{doc::DocumentInfo, revision::Revision},
|
||||||
errors::{internal_error, CollaborateError, CollaborateResult},
|
errors::{internal_error, CollaborateError, CollaborateResult},
|
||||||
|
sync::{RevisionSynchronizer, RevisionUser},
|
||||||
};
|
};
|
||||||
use async_stream::stream;
|
use async_stream::stream;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
@ -96,16 +94,22 @@ impl ServerDocumentManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct OpenDocHandle {
|
struct OpenDocHandle {
|
||||||
sender: mpsc::Sender<EditCommand>,
|
sender: mpsc::Sender<DocumentCommand>,
|
||||||
persistence: Arc<dyn DocumentPersistence>,
|
persistence: Arc<dyn DocumentPersistence>,
|
||||||
|
users: DashMap<String, Arc<dyn RevisionUser>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OpenDocHandle {
|
impl OpenDocHandle {
|
||||||
fn new(doc: DocumentInfo, persistence: Arc<dyn DocumentPersistence>) -> Result<Self, CollaborateError> {
|
fn new(doc: DocumentInfo, persistence: Arc<dyn DocumentPersistence>) -> Result<Self, CollaborateError> {
|
||||||
let (sender, receiver) = mpsc::channel(100);
|
let (sender, receiver) = mpsc::channel(100);
|
||||||
let queue = EditCommandQueue::new(receiver, doc)?;
|
let users = DashMap::new();
|
||||||
|
let queue = DocumentCommandQueue::new(receiver, doc)?;
|
||||||
tokio::task::spawn(queue.run());
|
tokio::task::spawn(queue.run());
|
||||||
Ok(Self { sender, persistence })
|
Ok(Self {
|
||||||
|
sender,
|
||||||
|
persistence,
|
||||||
|
users,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn apply_revisions(
|
async fn apply_revisions(
|
||||||
@ -115,7 +119,8 @@ impl OpenDocHandle {
|
|||||||
) -> Result<(), CollaborateError> {
|
) -> Result<(), CollaborateError> {
|
||||||
let (ret, rx) = oneshot::channel();
|
let (ret, rx) = oneshot::channel();
|
||||||
let persistence = self.persistence.clone();
|
let persistence = self.persistence.clone();
|
||||||
let msg = EditCommand::ApplyRevisions {
|
self.users.insert(user.user_id(), user.clone());
|
||||||
|
let msg = DocumentCommand::ApplyRevisions {
|
||||||
user,
|
user,
|
||||||
revisions,
|
revisions,
|
||||||
persistence,
|
persistence,
|
||||||
@ -127,11 +132,11 @@ impl OpenDocHandle {
|
|||||||
|
|
||||||
pub async fn document_json(&self) -> CollaborateResult<String> {
|
pub async fn document_json(&self) -> CollaborateResult<String> {
|
||||||
let (ret, rx) = oneshot::channel();
|
let (ret, rx) = oneshot::channel();
|
||||||
let msg = EditCommand::GetDocumentJson { ret };
|
let msg = DocumentCommand::GetDocumentJson { ret };
|
||||||
self.send(msg, rx).await?
|
self.send(msg, rx).await?
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send<T>(&self, msg: EditCommand, rx: oneshot::Receiver<T>) -> CollaborateResult<T> {
|
async fn send<T>(&self, msg: DocumentCommand, rx: oneshot::Receiver<T>) -> CollaborateResult<T> {
|
||||||
let _ = self.sender.send(msg).await.map_err(internal_error)?;
|
let _ = self.sender.send(msg).await.map_err(internal_error)?;
|
||||||
let result = rx.await.map_err(internal_error)?;
|
let result = rx.await.map_err(internal_error)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
@ -139,7 +144,7 @@ impl OpenDocHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum EditCommand {
|
enum DocumentCommand {
|
||||||
ApplyRevisions {
|
ApplyRevisions {
|
||||||
user: Arc<dyn RevisionUser>,
|
user: Arc<dyn RevisionUser>,
|
||||||
revisions: Vec<Revision>,
|
revisions: Vec<Revision>,
|
||||||
@ -151,17 +156,15 @@ enum EditCommand {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EditCommandQueue {
|
struct DocumentCommandQueue {
|
||||||
pub doc_id: String,
|
pub doc_id: String,
|
||||||
receiver: Option<mpsc::Receiver<EditCommand>>,
|
receiver: Option<mpsc::Receiver<DocumentCommand>>,
|
||||||
synchronizer: Arc<RevisionSynchronizer>,
|
synchronizer: Arc<RevisionSynchronizer>,
|
||||||
users: DashMap<String, Arc<dyn RevisionUser>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditCommandQueue {
|
impl DocumentCommandQueue {
|
||||||
fn new(receiver: mpsc::Receiver<EditCommand>, doc: DocumentInfo) -> Result<Self, CollaborateError> {
|
fn new(receiver: mpsc::Receiver<DocumentCommand>, doc: DocumentInfo) -> Result<Self, CollaborateError> {
|
||||||
let delta = RichTextDelta::from_bytes(&doc.text)?;
|
let delta = RichTextDelta::from_bytes(&doc.text)?;
|
||||||
let users = DashMap::new();
|
|
||||||
let synchronizer = Arc::new(RevisionSynchronizer::new(
|
let synchronizer = Arc::new(RevisionSynchronizer::new(
|
||||||
&doc.id,
|
&doc.id,
|
||||||
doc.rev_id,
|
doc.rev_id,
|
||||||
@ -172,7 +175,6 @@ impl EditCommandQueue {
|
|||||||
doc_id: doc.id,
|
doc_id: doc.id,
|
||||||
receiver: Some(receiver),
|
receiver: Some(receiver),
|
||||||
synchronizer,
|
synchronizer,
|
||||||
users,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,22 +195,21 @@ impl EditCommandQueue {
|
|||||||
stream.for_each(|msg| self.handle_message(msg)).await;
|
stream.for_each(|msg| self.handle_message(msg)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_message(&self, msg: EditCommand) {
|
async fn handle_message(&self, msg: DocumentCommand) {
|
||||||
match msg {
|
match msg {
|
||||||
EditCommand::ApplyRevisions {
|
DocumentCommand::ApplyRevisions {
|
||||||
user,
|
user,
|
||||||
revisions,
|
revisions,
|
||||||
persistence,
|
persistence,
|
||||||
ret,
|
ret,
|
||||||
} => {
|
} => {
|
||||||
self.users.insert(user.user_id(), user.clone());
|
|
||||||
self.synchronizer
|
self.synchronizer
|
||||||
.apply_revisions(user, revisions, persistence)
|
.apply_revisions(user, revisions, persistence)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let _ = ret.send(Ok(()));
|
let _ = ret.send(Ok(()));
|
||||||
},
|
},
|
||||||
EditCommand::GetDocumentJson { ret } => {
|
DocumentCommand::GetDocumentJson { ret } => {
|
||||||
let synchronizer = self.synchronizer.clone();
|
let synchronizer = self.synchronizer.clone();
|
||||||
let json = spawn_blocking(move || synchronizer.doc_json())
|
let json = spawn_blocking(move || synchronizer.doc_json())
|
||||||
.await
|
.await
|
@ -1,9 +1,10 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
core::{document::Document, sync::DocumentPersistence},
|
document::Document,
|
||||||
entities::{
|
entities::{
|
||||||
revision::{Revision, RevisionRange},
|
revision::{Revision, RevisionRange},
|
||||||
ws::{DocumentWSData, DocumentWSDataBuilder},
|
ws::{DocumentWSData, DocumentWSDataBuilder},
|
||||||
},
|
},
|
||||||
|
sync::DocumentPersistence,
|
||||||
};
|
};
|
||||||
use lib_ot::{core::OperationTransformable, errors::OTError, rich_text::RichTextDelta};
|
use lib_ot::{core::OperationTransformable, errors::OTError, rich_text::RichTextDelta};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
Reference in New Issue
Block a user