feat: add lru cache for document/database instance (#3938)

This commit is contained in:
Nathan.fooo
2023-11-14 17:21:09 +08:00
committed by GitHub
parent 4992f9c281
commit 1c500fbfc5
8 changed files with 83 additions and 88 deletions

View File

@ -863,7 +863,7 @@ dependencies = [
[[package]] [[package]]
name = "collab" name = "collab"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -883,7 +883,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-database" name = "collab-database"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -913,7 +913,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-derive" name = "collab-derive"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -925,7 +925,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-document" name = "collab-document"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",
@ -945,7 +945,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-entity" name = "collab-entity"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -959,7 +959,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-folder" name = "collab-folder"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@ -1001,7 +1001,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-persistence" name = "collab-persistence"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1023,7 +1023,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-plugins" name = "collab-plugins"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1050,7 +1050,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-user" name = "collab-user"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",
@ -2012,6 +2012,7 @@ dependencies = [
"lazy_static", "lazy_static",
"lib-dispatch", "lib-dispatch",
"lib-infra", "lib-infra",
"lru",
"nanoid", "nanoid",
"parking_lot", "parking_lot",
"protobuf", "protobuf",

View File

@ -66,14 +66,14 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "fe9
# To switch to the local path, run: # To switch to the local path, run:
# scripts/tool/update_collab_source.sh # scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️ # ⚠️⚠️⚠️️
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }

View File

@ -730,7 +730,7 @@ dependencies = [
[[package]] [[package]]
name = "collab" name = "collab"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -750,7 +750,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-database" name = "collab-database"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -780,7 +780,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-derive" name = "collab-derive"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -792,7 +792,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-document" name = "collab-document"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",
@ -812,7 +812,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-entity" name = "collab-entity"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -826,7 +826,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-folder" name = "collab-folder"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@ -868,7 +868,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-persistence" name = "collab-persistence"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -890,7 +890,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-plugins" name = "collab-plugins"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -917,7 +917,7 @@ dependencies = [
[[package]] [[package]]
name = "collab-user" name = "collab-user"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=da072600#da07260061c6ace8bca0bee1504f333fb8061713" source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=b8097fa891bdbb5826d6e480460c50ab66d26881#b8097fa891bdbb5826d6e480460c50ab66d26881"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"collab", "collab",
@ -1833,6 +1833,7 @@ dependencies = [
"lazy_static", "lazy_static",
"lib-dispatch", "lib-dispatch",
"lib-infra", "lib-infra",
"lru",
"nanoid", "nanoid",
"parking_lot", "parking_lot",
"protobuf", "protobuf",

View File

@ -109,11 +109,11 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "fe9
# To switch to the local path, run: # To switch to the local path, run:
# scripts/tool/update_collab_source.sh # scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️ # ⚠️⚠️⚠️️
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "da072600" } collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "b8097fa891bdbb5826d6e480460c50ab66d26881" }

View File

@ -44,6 +44,7 @@ chrono-tz = "0.8.2"
csv = "1.1.6" csv = "1.1.6"
strum = "0.25" strum = "0.25"
strum_macros = "0.25" strum_macros = "0.25"
lru.workspace = true
[dev-dependencies] [dev-dependencies]
event-integration = { path = "../event-integration", default-features = false } event-integration = { path = "../event-integration", default-features = false }

View File

@ -1,9 +1,9 @@
use std::collections::HashMap; use std::num::NonZeroUsize;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use collab::core::collab::{CollabRawData, MutexCollab}; use collab::core::collab::{CollabRawData, MutexCollab};
use collab_database::blocks::BlockEvent; use collab_database::blocks::BlockEvent;
use collab_database::database::{DatabaseData, YrsDocAction}; use collab_database::database::{DatabaseData, MutexDatabase, YrsDocAction};
use collab_database::error::DatabaseError; use collab_database::error::DatabaseError;
use collab_database::user::{ use collab_database::user::{
CollabFuture, CollabObjectUpdate, CollabObjectUpdateByOid, DatabaseCollabService, CollabFuture, CollabObjectUpdate, CollabObjectUpdateByOid, DatabaseCollabService,
@ -12,7 +12,8 @@ use collab_database::user::{
use collab_database::views::{CreateDatabaseParams, CreateViewParams, DatabaseLayout}; use collab_database::views::{CreateDatabaseParams, CreateViewParams, DatabaseLayout};
use collab_entity::CollabType; use collab_entity::CollabType;
use futures::executor::block_on; use futures::executor::block_on;
use tokio::sync::RwLock; use lru::LruCache;
use tokio::sync::{Mutex, RwLock};
use tracing::{event, instrument, trace}; use tracing::{event, instrument, trace};
use collab_integrate::collab_builder::AppFlowyCollabBuilder; use collab_integrate::collab_builder::AppFlowyCollabBuilder;
@ -42,7 +43,7 @@ pub struct DatabaseManager {
user: Arc<dyn DatabaseUser>, user: Arc<dyn DatabaseUser>,
workspace_database: Arc<RwLock<Option<Arc<WorkspaceDatabase>>>>, workspace_database: Arc<RwLock<Option<Arc<WorkspaceDatabase>>>>,
task_scheduler: Arc<RwLock<TaskDispatcher>>, task_scheduler: Arc<RwLock<TaskDispatcher>>,
editors: RwLock<HashMap<String, Arc<DatabaseEditor>>>, editors: Mutex<LruCache<String, Arc<DatabaseEditor>>>,
collab_builder: Arc<AppFlowyCollabBuilder>, collab_builder: Arc<AppFlowyCollabBuilder>,
cloud_service: Arc<dyn DatabaseCloudService>, cloud_service: Arc<dyn DatabaseCloudService>,
} }
@ -54,11 +55,12 @@ impl DatabaseManager {
collab_builder: Arc<AppFlowyCollabBuilder>, collab_builder: Arc<AppFlowyCollabBuilder>,
cloud_service: Arc<dyn DatabaseCloudService>, cloud_service: Arc<dyn DatabaseCloudService>,
) -> Self { ) -> Self {
let editors = Mutex::new(LruCache::new(NonZeroUsize::new(5).unwrap()));
Self { Self {
user: database_user, user: database_user,
workspace_database: Default::default(), workspace_database: Default::default(),
task_scheduler, task_scheduler,
editors: Default::default(), editors,
collab_builder, collab_builder,
cloud_service, cloud_service,
} }
@ -83,7 +85,8 @@ impl DatabaseManager {
// Clear all existing tasks // Clear all existing tasks
self.task_scheduler.write().await.clear_task(); self.task_scheduler.write().await.clear_task();
// Release all existing editors // Release all existing editors
self.editors.write().await.clear(); self.editors.lock().await.clear();
*self.workspace_database.write().await = None;
let collab_db = self.user.collab_db(uid)?; let collab_db = self.user.collab_db(uid)?;
let collab_builder = UserDatabaseCollabServiceImpl { let collab_builder = UserDatabaseCollabServiceImpl {
@ -134,11 +137,8 @@ impl DatabaseManager {
); );
let workspace_database = let workspace_database =
WorkspaceDatabase::open(uid, collab, collab_db, config, collab_builder); WorkspaceDatabase::open(uid, collab, collab_db, config, collab_builder);
subscribe_block_event(&workspace_database);
*self.workspace_database.write().await = Some(Arc::new(workspace_database)); *self.workspace_database.write().await = Some(Arc::new(workspace_database));
// Remove all existing editors
self.editors.write().await.clear();
Ok(()) Ok(())
} }
@ -186,44 +186,42 @@ impl DatabaseManager {
} }
pub async fn get_database(&self, database_id: &str) -> FlowyResult<Arc<DatabaseEditor>> { pub async fn get_database(&self, database_id: &str) -> FlowyResult<Arc<DatabaseEditor>> {
if let Some(editor) = self.editors.read().await.get(database_id) { if let Some(editor) = self.editors.lock().await.get(database_id).cloned() {
return Ok(editor.clone()); return Ok(editor);
} }
self.open_database(database_id).await self.open_database(database_id).await
} }
pub async fn open_database(&self, database_id: &str) -> FlowyResult<Arc<DatabaseEditor>> { pub async fn open_database(&self, database_id: &str) -> FlowyResult<Arc<DatabaseEditor>> {
trace!("create new editor for database {}", database_id); trace!("create new editor for database {}", database_id);
let mut editors = self.editors.write().await; let database = self
.get_workspace_database()
let wdb = self.get_workspace_database().await?; .await?
let database = wdb
.get_database(database_id) .get_database(database_id)
.await .await
.ok_or_else(FlowyError::collab_not_sync)?; .ok_or_else(FlowyError::collab_not_sync)?;
// Subscribe the [BlockEvent]
subscribe_block_event(&database);
let editor = Arc::new(DatabaseEditor::new(database, self.task_scheduler.clone()).await?); let editor = Arc::new(DatabaseEditor::new(database, self.task_scheduler.clone()).await?);
editors.insert(database_id.to_string(), editor.clone()); self
.editors
.lock()
.await
.put(database_id.to_string(), editor.clone());
Ok(editor) Ok(editor)
} }
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn close_database_view<T: AsRef<str>>(&self, view_id: T) -> FlowyResult<()> { pub async fn close_database_view<T: AsRef<str>>(&self, view_id: T) -> FlowyResult<()> {
// TODO(natan): defer closing the database if the sync is not finished
let view_id = view_id.as_ref(); let view_id = view_id.as_ref();
let wdb = self.get_workspace_database().await?; let wdb = self.get_workspace_database().await?;
let database_id = wdb.get_database_id_with_view_id(view_id); let database_id = wdb.get_database_id_with_view_id(view_id);
if database_id.is_some() {
wdb.close_database(database_id.as_ref().unwrap());
}
if let Some(database_id) = database_id { if let Some(database_id) = database_id {
let mut editors = self.editors.write().await; let mut editors = self.editors.lock().await;
if let Some(editor) = editors.get(&database_id) { if let Some(editor) = editors.get(&database_id) {
if editor.close_view_editor(view_id).await { editor.close_view_editor(view_id).await;
editor.close().await;
editors.remove(&database_id);
}
} }
} }
@ -369,8 +367,8 @@ impl DatabaseManager {
} }
/// Send notification to all clients that are listening to the given object. /// Send notification to all clients that are listening to the given object.
fn subscribe_block_event(workspace_database: &WorkspaceDatabase) { fn subscribe_block_event(database: &Arc<MutexDatabase>) {
let mut block_event_rx = workspace_database.subscribe_block_event(); let mut block_event_rx = database.lock().subscribe_block_event();
af_spawn(async move { af_spawn(async move {
while let Ok(event) = block_event_rx.recv().await { while let Ok(event) = block_event_rx.recv().await {
match event { match event {

View File

@ -113,13 +113,13 @@ impl DatabaseEditor {
}) })
} }
/// Returns bool value indicating whether the database is empty.
///
#[tracing::instrument(level = "debug", skip_all)] #[tracing::instrument(level = "debug", skip_all)]
pub async fn close_view_editor(&self, view_id: &str) -> bool { pub async fn close_view_editor(&self, view_id: &str) -> bool {
self.database_views.close_view(view_id).await self.database_views.close_view(view_id).await
} }
pub async fn close(&self) {}
pub async fn get_layout_type(&self, view_id: &str) -> DatabaseLayout { pub async fn get_layout_type(&self, view_id: &str) -> DatabaseLayout {
let view = self.database_views.get_view_editor(view_id).await.ok(); let view = self.database_views.get_view_editor(view_id).await.ok();
if let Some(editor) = view { if let Some(editor) = view {

View File

@ -1,5 +1,6 @@
use std::num::NonZeroUsize;
use std::sync::Arc;
use std::sync::Weak; use std::sync::Weak;
use std::{collections::HashMap, sync::Arc};
use collab::core::collab::{CollabRawData, MutexCollab}; use collab::core::collab::{CollabRawData, MutexCollab};
use collab_document::blocks::DocumentData; use collab_document::blocks::DocumentData;
@ -7,7 +8,8 @@ use collab_document::document::Document;
use collab_document::document_data::{default_document_collab_data, default_document_data}; use collab_document::document_data::{default_document_collab_data, default_document_data};
use collab_document::YrsDocAction; use collab_document::YrsDocAction;
use collab_entity::CollabType; use collab_entity::CollabType;
use parking_lot::RwLock; use lru::LruCache;
use parking_lot::Mutex;
use tracing::{event, instrument}; use tracing::{event, instrument};
use collab_integrate::collab_builder::AppFlowyCollabBuilder; use collab_integrate::collab_builder::AppFlowyCollabBuilder;
@ -30,7 +32,7 @@ pub trait DocumentUser: Send + Sync {
pub struct DocumentManager { pub struct DocumentManager {
pub user: Arc<dyn DocumentUser>, pub user: Arc<dyn DocumentUser>,
collab_builder: Arc<AppFlowyCollabBuilder>, collab_builder: Arc<AppFlowyCollabBuilder>,
documents: Arc<RwLock<HashMap<String, Arc<MutexDocument>>>>, documents: Arc<Mutex<LruCache<String, Arc<MutexDocument>>>>,
#[allow(dead_code)] #[allow(dead_code)]
cloud_service: Arc<dyn DocumentCloudService>, cloud_service: Arc<dyn DocumentCloudService>,
storage_service: Weak<dyn FileStorageService>, storage_service: Weak<dyn FileStorageService>,
@ -43,17 +45,18 @@ impl DocumentManager {
cloud_service: Arc<dyn DocumentCloudService>, cloud_service: Arc<dyn DocumentCloudService>,
storage_service: Weak<dyn FileStorageService>, storage_service: Weak<dyn FileStorageService>,
) -> Self { ) -> Self {
let documents = Arc::new(Mutex::new(LruCache::new(NonZeroUsize::new(10).unwrap())));
Self { Self {
user, user,
collab_builder, collab_builder,
documents: Default::default(), documents,
cloud_service, cloud_service,
storage_service, storage_service,
} }
} }
pub async fn initialize(&self, _uid: i64, _workspace_id: String) -> FlowyResult<()> { pub async fn initialize(&self, _uid: i64, _workspace_id: String) -> FlowyResult<()> {
self.documents.write().clear(); self.documents.lock().clear();
Ok(()) Ok(())
} }
@ -101,8 +104,8 @@ impl DocumentManager {
/// Return the document /// Return the document
#[tracing::instrument(level = "debug", skip(self), err)] #[tracing::instrument(level = "debug", skip(self), err)]
pub async fn get_document(&self, doc_id: &str) -> FlowyResult<Arc<MutexDocument>> { pub async fn get_document(&self, doc_id: &str) -> FlowyResult<Arc<MutexDocument>> {
if let Some(doc) = self.documents.read().get(doc_id) { if let Some(doc) = self.documents.lock().get(doc_id).cloned() {
return Ok(doc.clone()); return Ok(doc);
} }
let mut updates = vec![]; let mut updates = vec![];
if !self.is_doc_exist(doc_id)? { if !self.is_doc_exist(doc_id)? {
@ -133,6 +136,7 @@ impl DocumentManager {
} }
let uid = self.user.user_id()?; let uid = self.user.user_id()?;
event!(tracing::Level::DEBUG, "Initialize document: {}", doc_id);
let collab = self.collab_for_document(uid, doc_id, updates).await?; let collab = self.collab_for_document(uid, doc_id, updates).await?;
let document = Arc::new(MutexDocument::open(doc_id, collab)?); let document = Arc::new(MutexDocument::open(doc_id, collab)?);
@ -140,8 +144,8 @@ impl DocumentManager {
// and we don't want to subscribe to the document changes if we open the same document again. // and we don't want to subscribe to the document changes if we open the same document again.
self self
.documents .documents
.write() .lock()
.insert(doc_id.to_string(), document.clone()); .put(doc_id.to_string(), document.clone());
Ok(document) Ok(document)
} }
@ -162,7 +166,8 @@ impl DocumentManager {
#[instrument(level = "debug", skip(self), err)] #[instrument(level = "debug", skip(self), err)]
pub fn close_document(&self, doc_id: &str) -> FlowyResult<()> { pub fn close_document(&self, doc_id: &str) -> FlowyResult<()> {
self.documents.write().remove(doc_id); // TODO(nathan): remove the document from lru cache. Currently, we don't remove it from the cache.
// The lru will pop the least recently used document when the cache is full.
Ok(()) Ok(())
} }
@ -173,7 +178,9 @@ impl DocumentManager {
txn.delete_doc(uid, &doc_id)?; txn.delete_doc(uid, &doc_id)?;
Ok(()) Ok(())
}); });
self.documents.write().remove(doc_id);
// When deleting a document, we need to remove it from the cache.
self.documents.lock().pop(doc_id);
} }
Ok(()) Ok(())
} }
@ -213,19 +220,6 @@ impl DocumentManager {
.build(uid, doc_id, CollabType::Document, updates, db) .build(uid, doc_id, CollabType::Document, updates, db)
.await?; .await?;
Ok(collab) Ok(collab)
// let doc_id = doc_id.to_string();
// let (tx, rx) = oneshot::channel();
// let collab_builder = self.collab_builder.clone();
// tokio::spawn(async move {
// let collab = collab_builder
// .build(uid, &doc_id, CollabType::Document, updates, db)
// .await
// .unwrap();
// let _ = tx.send(collab);
// });
//
// Ok(rx.await.unwrap())
} }
fn is_doc_exist(&self, doc_id: &str) -> FlowyResult<bool> { fn is_doc_exist(&self, doc_id: &str) -> FlowyResult<bool> {