holding opened file handler

This commit is contained in:
appflowy 2021-09-13 23:09:57 +08:00
parent 30a7149764
commit c5d1a90009
11 changed files with 128 additions and 34 deletions

View File

@ -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" }

View File

@ -10,3 +10,7 @@ impl DocId {
Ok(Self(s))
}
}
impl AsRef<str> for DocId {
fn as_ref(&self) -> &str { &self.0 }
}

View File

@ -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<flowy_database::Error> for DocError {
// fn from(error: r2d2::Error) -> Self {
// ErrorBuilder::new(ErrorCode::InternalError).error(error).build() } }
impl std::convert::From<FileError> for DocError {
fn from(error: FileError) -> Self { ErrorBuilder::new(ErrorCode::InternalError).error(error).build() }
}
// impl std::convert::From<flowy_sqlite::Error> for DocError {
// fn from(error: flowy_sqlite::Error) -> Self {
// ErrorBuilder::new(ErrorCode::InternalError).error(error).build() } }

View File

@ -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<dyn DocumentUser>,
file_manager: RwLock<FileManager>,
pub doc: Arc<DocController>,
pub struct FlowyDocument {
controller: Arc<DocController>,
manager: Arc<DocManager>,
}
impl Document {
pub fn new(user: Arc<dyn DocumentUser>) -> Document {
impl FlowyDocument {
pub fn new(user: Arc<dyn DocumentUser>) -> 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<ConnectionPool>) -> Result<Doc, DocError> {
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(())
}
}

View File

@ -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<String> for DocId {
fn from(s: String) -> Self { DocId(s) }
}
pub(crate) struct DocManager {
inner: DashMap<DocId, RwLock<DocInfo>>,
}
impl DocManager {
pub(crate) fn new() -> Self { Self { inner: DashMap::new() } }
pub(crate) fn open<T, D>(&self, id: T, data: D) -> Result<(), DocError>
where
T: Into<DocId>,
D: TryInto<Delta, Error = DocError>,
{
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<T, F>(&self, id: T, f: F) -> Result<(), DocError>
where
T: Into<DocId>,
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<T>(&self, id: T) -> Result<(), DocError>
where
T: Into<DocId>,
{
let doc_id = id.into();
self.inner.remove(&doc_id);
Ok(())
}
}

View File

@ -0,0 +1,3 @@
mod doc_manager;
pub use doc_manager::*;

View File

@ -1,3 +1,3 @@
pub mod doc_controller;
pub mod file_manager;
pub(crate) mod doc_manager;
pub mod server;

View File

@ -8,9 +8,9 @@ mod delete;
mod format;
mod insert;
pub type InsertExtension = Box<dyn InsertExt>;
pub type FormatExtension = Box<dyn FormatExt>;
pub type DeleteExtension = Box<dyn DeleteExt>;
pub type InsertExtension = Box<dyn InsertExt + Send + Sync>;
pub type FormatExtension = Box<dyn FormatExt + Send + Sync>;
pub type DeleteExtension = Box<dyn DeleteExt + Send + Sync>;
pub trait InsertExt {
fn ext_name(&self) -> &str;

View File

@ -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<Module> {
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),

View File

@ -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<dyn WorkspaceUser>, database: Arc<dyn WorkspaceDatabase>, document: Arc<Document>) -> Module {
pub fn create(user: Arc<dyn WorkspaceUser>, database: Arc<dyn WorkspaceDatabase>, document: Arc<FlowyDocument>) -> 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()));

View File

@ -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<ViewTableSql>,
server: Server,
database: Arc<dyn WorkspaceDatabase>,
document: Arc<Document>,
document: Arc<FlowyDocument>,
}
impl ViewController {
pub(crate) fn new(user: Arc<dyn WorkspaceUser>, database: Arc<dyn WorkspaceDatabase>, server: Server, document: Arc<Document>) -> Self {
pub(crate) fn new(
user: Arc<dyn WorkspaceUser>,
database: Arc<dyn WorkspaceDatabase>,
server: Server,
document: Arc<FlowyDocument>,
) -> 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, &params.data), conn)?;
self.document.create(CreateDocParams::new(&view.id, &params.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<Doc, WorkspaceError> {
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(&params.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(())
}
}