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:
parent
95e0418d97
commit
2b9ce79ed4
@ -3,13 +3,12 @@ use crate::services::{
|
||||
persistence::{create_doc, read_doc},
|
||||
ws_actor::{DocumentWebSocketActor, WSActorMessage},
|
||||
},
|
||||
web_socket::{WSClientData, WebSocketReceiver},
|
||||
web_socket::{WebSocketReceiver, WSClientData},
|
||||
};
|
||||
|
||||
use crate::context::FlowyPersistence;
|
||||
use backend_service::errors::ServerError;
|
||||
use flowy_collaboration::{
|
||||
core::sync::{DocumentPersistence, ServerDocumentManager},
|
||||
entities::{
|
||||
doc::{CreateDocParams, DocumentInfo},
|
||||
revision::{RepeatedRevision, Revision},
|
||||
@ -25,6 +24,7 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
use tokio::sync::{mpsc, oneshot};
|
||||
use flowy_collaboration::sync::{DocumentPersistence, ServerDocumentManager};
|
||||
|
||||
pub fn make_document_ws_receiver(persistence: Arc<FlowyPersistence>) -> Arc<DocumentWebSocketReceiver> {
|
||||
let document_persistence = Arc::new(DocumentPersistenceImpl(persistence.clone()));
|
||||
|
@ -7,13 +7,13 @@ use actix_rt::task::spawn_blocking;
|
||||
use crate::context::FlowyPersistence;
|
||||
use async_stream::stream;
|
||||
use backend_service::errors::{internal_error, Result, ServerError};
|
||||
use flowy_collaboration::{
|
||||
core::sync::{RevisionUser, ServerDocumentManager, SyncResponse},
|
||||
protobuf::{DocumentWSData, DocumentWSDataType, NewDocumentUser, Revision},
|
||||
};
|
||||
use flowy_collaboration::protobuf::{DocumentWSData, DocumentWSDataType, NewDocumentUser, Revision};
|
||||
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 tokio::sync::{mpsc, oneshot};
|
||||
|
||||
@ -93,7 +93,7 @@ impl DocumentWebSocketActor {
|
||||
DocumentWSDataType::Ack => Ok(()),
|
||||
DocumentWSDataType::PushRev => self.handle_pushed_rev(user, document_data.data).await,
|
||||
DocumentWSDataType::PullRev => Ok(()),
|
||||
DocumentWSDataType::UserConnect => self.handle_user_connect(user, document_data).await,
|
||||
DocumentWSDataType::UserConnect => Ok(()),
|
||||
};
|
||||
match result {
|
||||
Ok(_) => {},
|
||||
@ -105,18 +105,6 @@ impl DocumentWebSocketActor {
|
||||
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<()> {
|
||||
let repeated_revision = spawn_blocking(move || parse_from_bytes::<RepeatedRevision>(&data))
|
||||
.await
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use crate::util::helper::{ViewTest, *};
|
||||
use flowy_collaboration::{
|
||||
core::document::{Document, PlainDoc},
|
||||
document::{Document, PlainDoc},
|
||||
entities::{
|
||||
doc::{CreateDocParams, DocIdentifier},
|
||||
revision::{md5, RepeatedRevision, RevType, Revision},
|
||||
|
@ -4,7 +4,7 @@ use chrono::Utc;
|
||||
use lazy_static::lazy_static;
|
||||
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_net::entities::NetworkType;
|
||||
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use flowy_collaboration::{
|
||||
core::document::history::UndoResult,
|
||||
document::history::UndoResult,
|
||||
entities::{
|
||||
doc::DocumentDelta,
|
||||
revision::{RevId, RevType, Revision},
|
||||
|
@ -1,7 +1,6 @@
|
||||
use async_stream::stream;
|
||||
|
||||
use flowy_collaboration::{
|
||||
core::document::{history::UndoResult, Document},
|
||||
entities::revision::Revision,
|
||||
errors::CollaborateError,
|
||||
};
|
||||
@ -13,6 +12,7 @@ use lib_ot::{
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::{mpsc, oneshot, RwLock};
|
||||
use flowy_collaboration::document::{Document, history::UndoResult};
|
||||
|
||||
pub(crate) struct EditorCommandQueue {
|
||||
doc_id: String,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use flowy_collaboration::{
|
||||
core::document::default::initial_delta_string,
|
||||
document::default::initial_delta_string,
|
||||
entities::doc::{CreateDocParams, DocIdentifier, DocumentInfo, ResetDocumentParams},
|
||||
};
|
||||
use lib_infra::future::FutureResult;
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![cfg_attr(rustfmt, rustfmt::skip)]
|
||||
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 unicode_segmentation::UnicodeSegmentation;
|
||||
use lib_ot::rich_text::RichTextDelta;
|
||||
|
@ -5,7 +5,7 @@ mod serde_test;
|
||||
mod undo_redo_test;
|
||||
|
||||
use derive_more::Display;
|
||||
use flowy_collaboration::core::document::{CustomDocument, Document};
|
||||
use flowy_collaboration::document::{CustomDocument, Document};
|
||||
use lib_ot::{
|
||||
core::*,
|
||||
rich_text::{RichTextAttribute, RichTextAttributes, RichTextDelta},
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![allow(clippy::all)]
|
||||
use crate::editor::{Rng, TestBuilder, TestOp::*};
|
||||
use flowy_collaboration::core::document::{FlowyDoc, PlainDoc};
|
||||
use flowy_collaboration::document::{FlowyDoc, PlainDoc};
|
||||
use lib_ot::{
|
||||
core::*,
|
||||
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::{
|
||||
core::*,
|
||||
rich_text::{AttributeBuilder, RichTextAttribute, RichTextAttributeValue, RichTextDelta},
|
||||
|
@ -1,5 +1,5 @@
|
||||
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};
|
||||
|
||||
#[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]
|
||||
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()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::core::document::default::initial_read_me;
|
||||
use crate::document::default::initial_read_me;
|
||||
|
||||
#[test]
|
||||
fn load_read_me() {
|
@ -6,7 +6,7 @@ use lib_ot::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
core::document::{
|
||||
document::{
|
||||
default::initial_delta,
|
||||
history::{History, UndoResult},
|
||||
view::{View, RECORD_THRESHOLD},
|
@ -1,4 +1,4 @@
|
||||
use crate::core::document::DeleteExt;
|
||||
use crate::document::DeleteExt;
|
||||
use lib_ot::{
|
||||
core::{DeltaBuilder, Interval},
|
||||
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::{
|
||||
core::{Attributes, CharMetric, DeltaBuilder, DeltaIter, Interval, NEW_LINE},
|
||||
rich_text::{plain_attributes, RichTextDelta},
|
@ -4,7 +4,7 @@ use lib_ot::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
core::document::{extensions::helper::line_break, FormatExt},
|
||||
document::{extensions::helper::line_break, FormatExt},
|
||||
util::find_newline,
|
||||
};
|
||||
|
@ -4,7 +4,7 @@ use lib_ot::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
core::document::{extensions::helper::line_break, FormatExt},
|
||||
document::{extensions::helper::line_break, FormatExt},
|
||||
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::{
|
||||
core::{is_empty_line_at_index, DeltaBuilder, DeltaIter},
|
||||
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::{
|
||||
core::{count_utf16_code_units, DeltaBuilder, DeltaIter},
|
||||
rich_text::{plain_attributes, RichTextAttribute, RichTextAttributes, RichTextDelta},
|
@ -1,4 +1,4 @@
|
||||
use crate::core::document::InsertExt;
|
||||
use crate::document::InsertExt;
|
||||
use lib_ot::{
|
||||
core::{Attributes, DeltaBuilder, DeltaIter, NEW_LINE},
|
||||
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_format::*;
|
||||
pub use default_insert::*;
|
@ -1,4 +1,4 @@
|
||||
use crate::{core::document::InsertExt, util::is_newline};
|
||||
use crate::util::is_newline;
|
||||
use lib_ot::{
|
||||
core::{DeltaBuilder, DeltaIter, NEW_LINE},
|
||||
rich_text::{
|
||||
@ -10,6 +10,7 @@ use lib_ot::{
|
||||
RichTextDelta,
|
||||
},
|
||||
};
|
||||
use crate::document::InsertExt;
|
||||
|
||||
pub struct PreserveBlockFormatOnInsert {}
|
||||
impl InsertExt for PreserveBlockFormatOnInsert {
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
core::document::InsertExt,
|
||||
document::InsertExt,
|
||||
util::{contain_newline, is_newline},
|
||||
};
|
||||
use lib_ot::{
|
@ -1,8 +1,9 @@
|
||||
use crate::{core::document::InsertExt, util::is_newline};
|
||||
use crate::util::is_newline;
|
||||
use lib_ot::{
|
||||
core::{CharMetric, DeltaBuilder, DeltaIter, NEW_LINE},
|
||||
rich_text::{RichTextAttributeKey, RichTextAttributes, RichTextDelta},
|
||||
};
|
||||
use crate::document::InsertExt;
|
||||
|
||||
pub struct ResetLineFormatOnNewLine {}
|
||||
impl InsertExt for ResetLineFormatOnNewLine {
|
@ -1,4 +1,4 @@
|
||||
use crate::core::document::*;
|
||||
use crate::document::*;
|
||||
use lib_ot::{
|
||||
core::{trim, Interval},
|
||||
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 flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use lib_ot::rich_text::RichTextDelta;
|
||||
|
@ -8,7 +8,7 @@ use std::convert::{TryFrom, TryInto};
|
||||
|
||||
#[derive(Debug, Clone, ProtoBuf_Enum, Eq, PartialEq, Hash)]
|
||||
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,
|
||||
// The frontend receives the PushRev event means the backend is pushing the new revision to frontend
|
||||
PushRev = 1,
|
||||
|
@ -1,7 +1,8 @@
|
||||
pub mod core;
|
||||
pub mod document;
|
||||
pub mod entities;
|
||||
pub mod errors;
|
||||
pub mod protobuf;
|
||||
pub mod sync;
|
||||
pub mod util;
|
||||
|
||||
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 {
|
||||
fn value(&self) -> 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 {
|
||||
}
|
||||
|
||||
|
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::{
|
||||
core::{
|
||||
document::Document,
|
||||
sync::{RevisionSynchronizer, RevisionUser},
|
||||
},
|
||||
document::Document,
|
||||
entities::{doc::DocumentInfo, revision::Revision},
|
||||
errors::{internal_error, CollaborateError, CollaborateResult},
|
||||
sync::{RevisionSynchronizer, RevisionUser},
|
||||
};
|
||||
use async_stream::stream;
|
||||
use dashmap::DashMap;
|
||||
@ -96,16 +94,22 @@ impl ServerDocumentManager {
|
||||
}
|
||||
|
||||
struct OpenDocHandle {
|
||||
sender: mpsc::Sender<EditCommand>,
|
||||
sender: mpsc::Sender<DocumentCommand>,
|
||||
persistence: Arc<dyn DocumentPersistence>,
|
||||
users: DashMap<String, Arc<dyn RevisionUser>>,
|
||||
}
|
||||
|
||||
impl OpenDocHandle {
|
||||
fn new(doc: DocumentInfo, persistence: Arc<dyn DocumentPersistence>) -> Result<Self, CollaborateError> {
|
||||
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());
|
||||
Ok(Self { sender, persistence })
|
||||
Ok(Self {
|
||||
sender,
|
||||
persistence,
|
||||
users,
|
||||
})
|
||||
}
|
||||
|
||||
async fn apply_revisions(
|
||||
@ -115,7 +119,8 @@ impl OpenDocHandle {
|
||||
) -> Result<(), CollaborateError> {
|
||||
let (ret, rx) = oneshot::channel();
|
||||
let persistence = self.persistence.clone();
|
||||
let msg = EditCommand::ApplyRevisions {
|
||||
self.users.insert(user.user_id(), user.clone());
|
||||
let msg = DocumentCommand::ApplyRevisions {
|
||||
user,
|
||||
revisions,
|
||||
persistence,
|
||||
@ -127,11 +132,11 @@ impl OpenDocHandle {
|
||||
|
||||
pub async fn document_json(&self) -> CollaborateResult<String> {
|
||||
let (ret, rx) = oneshot::channel();
|
||||
let msg = EditCommand::GetDocumentJson { ret };
|
||||
let msg = DocumentCommand::GetDocumentJson { ret };
|
||||
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 result = rx.await.map_err(internal_error)?;
|
||||
Ok(result)
|
||||
@ -139,7 +144,7 @@ impl OpenDocHandle {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum EditCommand {
|
||||
enum DocumentCommand {
|
||||
ApplyRevisions {
|
||||
user: Arc<dyn RevisionUser>,
|
||||
revisions: Vec<Revision>,
|
||||
@ -151,17 +156,15 @@ enum EditCommand {
|
||||
},
|
||||
}
|
||||
|
||||
struct EditCommandQueue {
|
||||
struct DocumentCommandQueue {
|
||||
pub doc_id: String,
|
||||
receiver: Option<mpsc::Receiver<EditCommand>>,
|
||||
receiver: Option<mpsc::Receiver<DocumentCommand>>,
|
||||
synchronizer: Arc<RevisionSynchronizer>,
|
||||
users: DashMap<String, Arc<dyn RevisionUser>>,
|
||||
}
|
||||
|
||||
impl EditCommandQueue {
|
||||
fn new(receiver: mpsc::Receiver<EditCommand>, doc: DocumentInfo) -> Result<Self, CollaborateError> {
|
||||
impl DocumentCommandQueue {
|
||||
fn new(receiver: mpsc::Receiver<DocumentCommand>, doc: DocumentInfo) -> Result<Self, CollaborateError> {
|
||||
let delta = RichTextDelta::from_bytes(&doc.text)?;
|
||||
let users = DashMap::new();
|
||||
let synchronizer = Arc::new(RevisionSynchronizer::new(
|
||||
&doc.id,
|
||||
doc.rev_id,
|
||||
@ -172,7 +175,6 @@ impl EditCommandQueue {
|
||||
doc_id: doc.id,
|
||||
receiver: Some(receiver),
|
||||
synchronizer,
|
||||
users,
|
||||
})
|
||||
}
|
||||
|
||||
@ -193,22 +195,21 @@ impl EditCommandQueue {
|
||||
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 {
|
||||
EditCommand::ApplyRevisions {
|
||||
DocumentCommand::ApplyRevisions {
|
||||
user,
|
||||
revisions,
|
||||
persistence,
|
||||
ret,
|
||||
} => {
|
||||
self.users.insert(user.user_id(), user.clone());
|
||||
self.synchronizer
|
||||
.apply_revisions(user, revisions, persistence)
|
||||
.await
|
||||
.unwrap();
|
||||
let _ = ret.send(Ok(()));
|
||||
},
|
||||
EditCommand::GetDocumentJson { ret } => {
|
||||
DocumentCommand::GetDocumentJson { ret } => {
|
||||
let synchronizer = self.synchronizer.clone();
|
||||
let json = spawn_blocking(move || synchronizer.doc_json())
|
||||
.await
|
@ -1,9 +1,10 @@
|
||||
use crate::{
|
||||
core::{document::Document, sync::DocumentPersistence},
|
||||
document::Document,
|
||||
entities::{
|
||||
revision::{Revision, RevisionRange},
|
||||
ws::{DocumentWSData, DocumentWSDataBuilder},
|
||||
},
|
||||
sync::DocumentPersistence,
|
||||
};
|
||||
use lib_ot::{core::OperationTransformable, errors::OTError, rich_text::RichTextDelta};
|
||||
use parking_lot::RwLock;
|
Loading…
Reference in New Issue
Block a user