fix: doc open sync (#4732)

* chore: bump client api

* fix: open document and folder

* chore: bump collab rev

* chore: fix wasm build

* chore: fix warnings
This commit is contained in:
Nathan.fooo
2024-02-25 07:49:44 +08:00
committed by GitHub
parent 4ca3ba8e08
commit c3e5aa29fc
20 changed files with 295 additions and 221 deletions

View File

@ -18,7 +18,7 @@ flowy-notification = { workspace = true }
parking_lot.workspace = true
unicode-segmentation = "1.10"
tracing.workspace = true
flowy-error = { path = "../flowy-error", features = ["impl_from_dispatch_error"]}
flowy-error = { path = "../flowy-error", features = ["impl_from_dispatch_error", "impl_from_collab_folder"]}
lib-dispatch = { workspace = true }
bytes.workspace = true
lib-infra = { workspace = true }

View File

@ -4,8 +4,10 @@ use std::sync::{Arc, Weak};
use collab::core::collab::{CollabDocState, MutexCollab};
use collab_entity::CollabType;
use collab_folder::error::FolderError;
use collab_folder::{
Folder, FolderData, Section, SectionItem, TrashInfo, View, ViewLayout, ViewUpdate, Workspace,
Folder, FolderData, FolderNotify, Section, SectionItem, TrashInfo, UserId, View, ViewLayout,
ViewUpdate, Workspace,
};
use parking_lot::{Mutex, RwLock};
use tracing::{error, info, instrument};
@ -15,6 +17,7 @@ use collab_integrate::{CollabKVDB, CollabPersistenceConfig};
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use flowy_folder_pub::cloud::{gen_view_id, FolderCloudService};
use flowy_folder_pub::folder_builder::ParentChildViews;
use lib_infra::conditional_send_sync_trait;
use crate::entities::icon::UpdateViewIconParams;
@ -46,7 +49,7 @@ conditional_send_sync_trait! {
pub struct FolderManager {
pub(crate) workspace_id: RwLock<Option<String>>,
pub(crate) mutex_folder: Arc<MutexFolder>,
collab_builder: Arc<AppFlowyCollabBuilder>,
pub(crate) collab_builder: Arc<AppFlowyCollabBuilder>,
pub(crate) user: Arc<dyn FolderUser>,
pub(crate) operation_handlers: FolderOperationHandlers,
pub cloud_service: Arc<dyn FolderCloudService>,
@ -147,13 +150,15 @@ impl FolderManager {
Ok(views)
}
pub(crate) async fn collab_for_folder(
pub(crate) async fn make_folder<T: Into<Option<FolderNotify>>>(
&self,
uid: i64,
workspace_id: &str,
collab_db: Weak<CollabKVDB>,
collab_doc_state: CollabDocState,
) -> Result<Arc<MutexCollab>, FlowyError> {
folder_notifier: T,
) -> Result<Folder, FlowyError> {
let folder_notifier = folder_notifier.into();
let collab = self
.collab_builder
.build_with_config(
@ -168,6 +173,45 @@ impl FolderManager {
CollabBuilderConfig::default().sync_enable(true),
)
.await?;
let (should_clear, err) = match Folder::open(UserId::from(uid), collab, folder_notifier) {
Ok(folder) => {
return Ok(folder);
},
Err(err) => (matches!(err, FolderError::NoRequiredData(_)), err),
};
// If opening the folder fails due to missing required data (indicated by a `FolderError::NoRequiredData`),
// the function logs an informational message and attempts to clear the folder data by deleting its
// document from the collaborative database. It then returns the encountered error.
if should_clear {
info!("Clear the folder data and try to open the folder again");
if let Some(db) = self.user.collab_db(uid).ok().and_then(|a| a.upgrade()) {
let _ = db.delete_doc(uid, workspace_id).await;
}
}
Err(err.into())
}
pub(crate) async fn create_empty_collab(
&self,
uid: i64,
workspace_id: &str,
collab_db: Weak<CollabKVDB>,
) -> Result<Arc<MutexCollab>, FlowyError> {
let collab = self
.collab_builder
.build_with_config(
uid,
workspace_id,
CollabType::Folder,
collab_db,
vec![],
CollabPersistenceConfig::new()
.enable_snapshot(true)
.snapshot_per_update(50),
CollabBuilderConfig::default().sync_enable(true),
)
.await?;
Ok(collab)
}

View File

@ -1,7 +1,11 @@
use collab_entity::CollabType;
use collab_folder::{Folder, FolderNotify, UserId};
use collab_integrate::CollabKVDB;
use flowy_error::{FlowyError, FlowyResult};
use std::sync::{Arc, Weak};
use tracing::{event, Level};
@ -48,8 +52,9 @@ impl FolderManager {
let is_exist = self.is_workspace_exist_in_local(uid, &workspace_id).await;
// 1. if the folder exists, open it from local disk
if is_exist {
event!(Level::INFO, "Init folder from local disk");
self
.open_local_folder(uid, &workspace_id, collab_db, folder_notifier)
.make_folder(uid, &workspace_id, collab_db, vec![], folder_notifier)
.await?
} else if create_if_not_exist {
// 2. if the folder doesn't exist and create_if_not_exist is true, create a default folder
@ -66,30 +71,40 @@ impl FolderManager {
.get_folder_doc_state(&workspace_id, uid, CollabType::Folder, &workspace_id)
.await?;
let collab = self
.collab_for_folder(uid, &workspace_id, collab_db.clone(), doc_state)
.await?;
Folder::open(UserId::from(uid), collab, Some(folder_notifier.clone()))?
self
.make_folder(
uid,
&workspace_id,
collab_db.clone(),
doc_state,
folder_notifier.clone(),
)
.await?
}
},
FolderInitDataSource::Cloud(doc_state) => {
if doc_state.is_empty() {
event!(Level::ERROR, "remote folder data is empty, open from local");
self
.open_local_folder(uid, &workspace_id, collab_db, folder_notifier)
.make_folder(uid, &workspace_id, collab_db, vec![], folder_notifier)
.await?
} else {
event!(Level::INFO, "Restore folder with remote data");
let collab = self
.collab_for_folder(uid, &workspace_id, collab_db.clone(), doc_state)
.await?;
Folder::open(UserId::from(uid), collab, Some(folder_notifier.clone()))?
event!(Level::INFO, "Restore folder from remote data");
self
.make_folder(
uid,
&workspace_id,
collab_db.clone(),
doc_state,
folder_notifier.clone(),
)
.await?
}
},
FolderInitDataSource::FolderData(folder_data) => {
event!(Level::INFO, "Restore folder with passed-in folder data");
let collab = self
.collab_for_folder(uid, &workspace_id, collab_db, vec![])
.create_empty_collab(uid, &workspace_id, collab_db)
.await?;
Folder::create(
UserId::from(uid),
@ -135,7 +150,7 @@ impl FolderManager {
let folder_data =
DefaultFolderBuilder::build(uid, workspace_id.to_string(), &self.operation_handlers).await;
let collab = self
.collab_for_folder(uid, workspace_id, collab_db, vec![])
.create_empty_collab(uid, workspace_id, collab_db)
.await?;
Ok(Folder::create(
UserId::from(uid),
@ -144,19 +159,4 @@ impl FolderManager {
folder_data,
))
}
async fn open_local_folder(
&self,
uid: i64,
workspace_id: &str,
collab_db: Weak<CollabKVDB>,
folder_notifier: FolderNotify,
) -> Result<Folder, FlowyError> {
event!(Level::INFO, "Init folder from local disk");
let collab = self
.collab_for_folder(uid, workspace_id, collab_db, vec![])
.await?;
let folder = Folder::open(UserId::from(uid), collab, Some(folder_notifier))?;
Ok(folder)
}
}