From c5d1a90009e815ad529325df9552145385227bef Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 13 Sep 2021 23:09:57 +0800 Subject: [PATCH] holding opened file handler --- rust-lib/flowy-document/Cargo.toml | 3 + .../src/entities/doc/parser/doc_id.rs | 4 ++ rust-lib/flowy-document/src/errors.rs | 5 -- rust-lib/flowy-document/src/module.rs | 47 ++++++++++---- .../src/services/doc_manager/doc_manager.rs | 65 +++++++++++++++++++ .../src/services/doc_manager/mod.rs | 3 + rust-lib/flowy-document/src/services/mod.rs | 2 +- .../flowy-ot/src/client/extensions/mod.rs | 6 +- rust-lib/flowy-sdk/src/module.rs | 4 +- rust-lib/flowy-workspace/src/module.rs | 4 +- .../src/services/view_controller.rs | 19 ++++-- 11 files changed, 128 insertions(+), 34 deletions(-) create mode 100644 rust-lib/flowy-document/src/services/doc_manager/doc_manager.rs create mode 100644 rust-lib/flowy-document/src/services/doc_manager/mod.rs diff --git a/rust-lib/flowy-document/Cargo.toml b/rust-lib/flowy-document/Cargo.toml index de057488f1..0d8f622c4a 100644 --- a/rust-lib/flowy-document/Cargo.toml +++ b/rust-lib/flowy-document/Cargo.toml @@ -13,8 +13,10 @@ flowy-derive = { path = "../flowy-derive" } flowy-database = { path = "../flowy-database" } flowy-infra = { path = "../flowy-infra" } flowy-observable = { path = "../flowy-observable" } +flowy-ot = { path = "../flowy-ot" } flowy-net = { path = "../flowy-net", features = ["flowy_request"] } + diesel = {version = "1.4.7", features = ["sqlite"]} diesel_derives = {version = "1.4.1", features = ["sqlite"]} protobuf = {version = "2.18.0"} @@ -26,6 +28,7 @@ tracing = { version = "0.1", features = ["log"] } bytes = { version = "1.0" } strum = "0.21" strum_macros = "0.21" +dashmap = "4.0" [dev-dependencies] flowy-test = { path = "../flowy-test" } diff --git a/rust-lib/flowy-document/src/entities/doc/parser/doc_id.rs b/rust-lib/flowy-document/src/entities/doc/parser/doc_id.rs index fbdfc0fa56..a72a67e864 100644 --- a/rust-lib/flowy-document/src/entities/doc/parser/doc_id.rs +++ b/rust-lib/flowy-document/src/entities/doc/parser/doc_id.rs @@ -10,3 +10,7 @@ impl DocId { Ok(Self(s)) } } + +impl AsRef for DocId { + fn as_ref(&self) -> &str { &self.0 } +} diff --git a/rust-lib/flowy-document/src/errors.rs b/rust-lib/flowy-document/src/errors.rs index db4102b9bb..f649a8b1a9 100644 --- a/rust-lib/flowy-document/src/errors.rs +++ b/rust-lib/flowy-document/src/errors.rs @@ -1,4 +1,3 @@ -use crate::services::file_manager::FileError; use bytes::Bytes; use derive_more::Display; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; @@ -53,10 +52,6 @@ impl std::convert::From for DocError { // fn from(error: r2d2::Error) -> Self { // ErrorBuilder::new(ErrorCode::InternalError).error(error).build() } } -impl std::convert::From for DocError { - fn from(error: FileError) -> Self { ErrorBuilder::new(ErrorCode::InternalError).error(error).build() } -} - // impl std::convert::From for DocError { // fn from(error: flowy_sqlite::Error) -> Self { // ErrorBuilder::new(ErrorCode::InternalError).error(error).build() } } diff --git a/rust-lib/flowy-document/src/module.rs b/rust-lib/flowy-document/src/module.rs index 18759c07ad..b4ac74974d 100644 --- a/rust-lib/flowy-document/src/module.rs +++ b/rust-lib/flowy-document/src/module.rs @@ -1,8 +1,11 @@ use crate::{ errors::DocError, - services::{doc_controller::DocController, file_manager::FileManager, server::construct_doc_server}, + services::{doc_controller::DocController, doc_manager::DocManager, server::construct_doc_server}, }; +use crate::entities::doc::{CreateDocParams, Doc, QueryDocParams, UpdateDocParams}; +use diesel::SqliteConnection; +use flowy_database::ConnectionPool; use std::sync::Arc; use tokio::sync::RwLock; @@ -16,21 +19,37 @@ pub enum DocumentType { Doc, } -pub struct Document { - user: Arc, - file_manager: RwLock, - pub doc: Arc, +pub struct FlowyDocument { + controller: Arc, + manager: Arc, } -impl Document { - pub fn new(user: Arc) -> Document { +impl FlowyDocument { + pub fn new(user: Arc) -> FlowyDocument { let server = construct_doc_server(); - let doc_controller = Arc::new(DocController::new(server.clone(), user.clone())); - let file_manager = RwLock::new(FileManager::new(user.clone())); - Self { - user, - file_manager, - doc: doc_controller, - } + let manager = Arc::new(DocManager::new()); + let controller = Arc::new(DocController::new(server.clone(), user.clone())); + Self { controller, manager } + } + + pub fn create(&self, params: CreateDocParams, conn: &SqliteConnection) -> Result<(), DocError> { + let _ = self.controller.create(params, conn)?; + Ok(()) + } + + pub fn delete(&self, params: QueryDocParams, conn: &SqliteConnection) -> Result<(), DocError> { + let _ = self.controller.delete(params.into(), conn)?; + Ok(()) + } + + pub async fn open(&self, params: QueryDocParams, pool: Arc) -> Result { + let doc = self.controller.open(params, pool).await?; + + Ok(doc) + } + + pub fn update(&self, params: UpdateDocParams, conn: &SqliteConnection) -> Result<(), DocError> { + let _ = self.controller.update(params, conn)?; + Ok(()) } } diff --git a/rust-lib/flowy-document/src/services/doc_manager/doc_manager.rs b/rust-lib/flowy-document/src/services/doc_manager/doc_manager.rs new file mode 100644 index 0000000000..8896b15242 --- /dev/null +++ b/rust-lib/flowy-document/src/services/doc_manager/doc_manager.rs @@ -0,0 +1,65 @@ +use crate::errors::{DocError, ErrorBuilder, ErrorCode}; +use dashmap::{mapref::one::Ref, DashMap}; +use flowy_ot::{ + client::{Document, FlowyDoc}, + core::Delta, +}; +use std::convert::TryInto; +use tokio::sync::RwLock; + +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub struct DocId(pub(crate) String); + +pub struct DocInfo { + document: Document, +} + +impl std::convert::From for DocId { + fn from(s: String) -> Self { DocId(s) } +} + +pub(crate) struct DocManager { + inner: DashMap>, +} + +impl DocManager { + pub(crate) fn new() -> Self { Self { inner: DashMap::new() } } + pub(crate) fn open(&self, id: T, data: D) -> Result<(), DocError> + where + T: Into, + D: TryInto, + { + let doc_id = id.into(); + let delta = data.try_into()?; + let document = Document::from_delta(delta); + let doc_info = DocInfo { document }; + self.inner.insert(doc_id, RwLock::new(doc_info)); + Ok(()) + } + + pub(crate) async fn mut_doc(&self, id: T, f: F) -> Result<(), DocError> + where + T: Into, + F: FnOnce(&mut Document) -> Result<(), DocError>, + { + let doc_id = id.into(); + match self.inner.get(&doc_id) { + None => Err(ErrorBuilder::new(ErrorCode::DocNotfound) + .msg("Doc is close or you should call open first") + .build()), + Some(doc_info) => { + let mut write_guard = doc_info.write().await; + f(&mut write_guard.document) + }, + } + } + + pub(crate) fn close(&self, id: T) -> Result<(), DocError> + where + T: Into, + { + let doc_id = id.into(); + self.inner.remove(&doc_id); + Ok(()) + } +} diff --git a/rust-lib/flowy-document/src/services/doc_manager/mod.rs b/rust-lib/flowy-document/src/services/doc_manager/mod.rs new file mode 100644 index 0000000000..8e6ce1f8dc --- /dev/null +++ b/rust-lib/flowy-document/src/services/doc_manager/mod.rs @@ -0,0 +1,3 @@ +mod doc_manager; + +pub use doc_manager::*; diff --git a/rust-lib/flowy-document/src/services/mod.rs b/rust-lib/flowy-document/src/services/mod.rs index b48e08afb4..7ad8eed131 100644 --- a/rust-lib/flowy-document/src/services/mod.rs +++ b/rust-lib/flowy-document/src/services/mod.rs @@ -1,3 +1,3 @@ pub mod doc_controller; -pub mod file_manager; +pub(crate) mod doc_manager; pub mod server; diff --git a/rust-lib/flowy-ot/src/client/extensions/mod.rs b/rust-lib/flowy-ot/src/client/extensions/mod.rs index ac1f61772b..b52746ffc8 100644 --- a/rust-lib/flowy-ot/src/client/extensions/mod.rs +++ b/rust-lib/flowy-ot/src/client/extensions/mod.rs @@ -8,9 +8,9 @@ mod delete; mod format; mod insert; -pub type InsertExtension = Box; -pub type FormatExtension = Box; -pub type DeleteExtension = Box; +pub type InsertExtension = Box; +pub type FormatExtension = Box; +pub type DeleteExtension = Box; pub trait InsertExt { fn ext_name(&self) -> &str; diff --git a/rust-lib/flowy-sdk/src/module.rs b/rust-lib/flowy-sdk/src/module.rs index 8722661b4d..c4cfabefad 100644 --- a/rust-lib/flowy-sdk/src/module.rs +++ b/rust-lib/flowy-sdk/src/module.rs @@ -1,7 +1,7 @@ use flowy_dispatch::prelude::Module; use crate::deps_resolve::{EditorUserImpl, WorkspaceDatabaseImpl, WorkspaceUserImpl}; -use flowy_document::module::Document; +use flowy_document::module::FlowyDocument; use flowy_user::services::user::UserSessionBuilder; use std::sync::Arc; @@ -24,7 +24,7 @@ pub fn build_modules(config: ModuleConfig) -> Vec { user_session: user_session.clone(), }); - let document = Arc::new(Document::new(editor_user)); + let document = Arc::new(FlowyDocument::new(editor_user)); vec![ flowy_user::module::create(user_session), diff --git a/rust-lib/flowy-workspace/src/module.rs b/rust-lib/flowy-workspace/src/module.rs index 4ee6b2d5aa..bfc97b68ee 100644 --- a/rust-lib/flowy-workspace/src/module.rs +++ b/rust-lib/flowy-workspace/src/module.rs @@ -6,7 +6,7 @@ use crate::{ }; use flowy_database::DBConnection; use flowy_dispatch::prelude::*; -use flowy_document::module::Document; +use flowy_document::module::FlowyDocument; use flowy_sqlite::ConnectionPool; use std::sync::Arc; @@ -29,7 +29,7 @@ pub trait WorkspaceDatabase: Send + Sync { } } -pub fn create(user: Arc, database: Arc, document: Arc) -> Module { +pub fn create(user: Arc, database: Arc, document: Arc) -> Module { let server = construct_workspace_server(); let view_controller = Arc::new(ViewController::new(user.clone(), database.clone(), server.clone(), document)); let app_controller = Arc::new(AppController::new(user.clone(), database.clone(), server.clone())); diff --git a/rust-lib/flowy-workspace/src/services/view_controller.rs b/rust-lib/flowy-workspace/src/services/view_controller.rs index 0fea5fd913..a87e891a7a 100644 --- a/rust-lib/flowy-workspace/src/services/view_controller.rs +++ b/rust-lib/flowy-workspace/src/services/view_controller.rs @@ -15,7 +15,7 @@ use crate::{ use flowy_database::SqliteConnection; use flowy_document::{ entities::doc::{CreateDocParams, Doc, QueryDocParams, UpdateDocParams}, - module::Document, + module::FlowyDocument, }; use std::sync::Arc; @@ -24,11 +24,16 @@ pub(crate) struct ViewController { sql: Arc, server: Server, database: Arc, - document: Arc, + document: Arc, } impl ViewController { - pub(crate) fn new(user: Arc, database: Arc, server: Server, document: Arc) -> Self { + pub(crate) fn new( + user: Arc, + database: Arc, + server: Server, + document: Arc, + ) -> Self { let sql = Arc::new(ViewTableSql {}); Self { user, @@ -45,7 +50,7 @@ impl ViewController { // TODO: rollback anything created before if failed? conn.immediate_transaction::<_, WorkspaceError, _>(|| { let _ = self.save_view(view.clone(), conn)?; - self.document.doc.create(CreateDocParams::new(&view.id, ¶ms.data), conn)?; + self.document.create(CreateDocParams::new(&view.id, ¶ms.data), conn)?; let repeated_view = self.read_local_views_belong_to(&view.belong_to_id, conn)?; notify(&view.belong_to_id, WorkspaceObservable::AppCreateView) @@ -72,7 +77,7 @@ impl ViewController { } pub(crate) async fn open_view(&self, params: QueryDocParams) -> Result { - let doc = self.document.doc.open(params, self.database.db_pool()?).await?; + let doc = self.document.open(params, self.database.db_pool()?).await?; Ok(doc) } @@ -82,7 +87,7 @@ impl ViewController { conn.immediate_transaction::<_, WorkspaceError, _>(|| { let view_table = self.sql.delete_view(¶ms.view_id, conn)?; - let _ = self.document.doc.delete(params.into(), conn)?; + let _ = self.document.delete(params.into(), conn)?; let repeated_view = self.read_local_views_belong_to(&view_table.belong_to_id, conn)?; notify(&view_table.belong_to_id, WorkspaceObservable::AppDeleteView) @@ -121,7 +126,7 @@ impl ViewController { pub(crate) async fn update_view_data(&self, params: UpdateDocParams) -> Result<(), WorkspaceError> { let conn = &*self.database.db_connection()?; - let _ = self.document.doc.update(params, &*conn)?; + let _ = self.document.update(params, &*conn)?; Ok(()) } }