chore: pass folder init data

This commit is contained in:
Nathan 2025-04-20 18:07:02 +08:00
parent 791a79a234
commit 92d5690bba
10 changed files with 106 additions and 85 deletions

View file

@ -2835,6 +2835,7 @@ dependencies = [
"flowy-notification",
"flowy-search-pub",
"flowy-sqlite",
"flowy-user-pub",
"futures",
"lazy_static",
"lib-dispatch",

View file

@ -131,7 +131,7 @@ impl AIManager {
#[instrument(skip_all, err)]
pub async fn initialize_after_open_workspace(
&self,
_workspace_id: &str,
_workspace_id: &Uuid,
) -> Result<(), FlowyError> {
let local_ai = self.local_ai.clone();
tokio::spawn(async move {

View file

@ -253,6 +253,7 @@ impl AppFlowyCore {
.await;
let user_status_callback = UserStatusCallbackImpl {
user_manager: user_manager.clone(),
collab_builder,
folder_manager: folder_manager.clone(),
database_manager: database_manager.clone(),

View file

@ -4,23 +4,27 @@ use anyhow::Context;
use client_api::entity::billing_dto::SubscriptionPlan;
use tracing::{error, event, info};
use crate::server_layer::ServerProvider;
use collab_entity::CollabType;
use collab_integrate::collab_builder::AppFlowyCollabBuilder;
use collab_plugins::local_storage::kv::doc::CollabKVAction;
use collab_plugins::local_storage::kv::KVTransactionDB;
use flowy_ai::ai_manager::AIManager;
use flowy_database2::DatabaseManager;
use flowy_document::manager::DocumentManager;
use flowy_error::FlowyResult;
use flowy_error::{FlowyError, FlowyResult};
use flowy_folder::manager::{FolderInitDataSource, FolderManager};
use flowy_storage::manager::StorageManager;
use flowy_user::event_map::UserStatusCallback;
use flowy_user::user_manager::UserManager;
use flowy_user_pub::cloud::{UserCloudConfig, UserCloudServiceProvider};
use flowy_user_pub::entities::{AuthType, UserProfile, UserWorkspace};
use lib_dispatch::runtime::AFPluginRuntime;
use lib_infra::async_trait::async_trait;
use crate::server_layer::ServerProvider;
use uuid::Uuid;
pub(crate) struct UserStatusCallbackImpl {
pub(crate) user_manager: Arc<UserManager>,
pub(crate) collab_builder: Arc<AppFlowyCollabBuilder>,
pub(crate) folder_manager: Arc<FolderManager>,
pub(crate) database_manager: Arc<DatabaseManager>,
@ -42,6 +46,60 @@ impl UserStatusCallbackImpl {
}
});
}
async fn folder_init_data_source(
&self,
user_id: i64,
workspace_id: &Uuid,
auth_type: &AuthType,
) -> FlowyResult<FolderInitDataSource> {
let is_exist = self.is_object_exist_on_disk(user_id, workspace_id, workspace_id)?;
if is_exist {
Ok(FolderInitDataSource::LocalDisk {
create_if_not_exist: false,
})
} else {
let data_source = match self
.folder_manager
.cloud_service
.get_folder_doc_state(workspace_id, user_id, CollabType::Folder, workspace_id)
.await
{
Ok(doc_state) => match auth_type {
AuthType::Local => FolderInitDataSource::LocalDisk {
create_if_not_exist: true,
},
AuthType::AppFlowyCloud => FolderInitDataSource::Cloud(doc_state),
},
Err(err) => match auth_type {
AuthType::Local => FolderInitDataSource::LocalDisk {
create_if_not_exist: true,
},
AuthType::AppFlowyCloud => {
return Err(err);
},
},
};
Ok(data_source)
}
}
fn is_object_exist_on_disk(
&self,
user_id: i64,
workspace_id: &Uuid,
object_id: &Uuid,
) -> FlowyResult<bool> {
let db = self
.user_manager
.get_collab_db(user_id)?
.upgrade()
.ok_or_else(|| FlowyError::internal().with_context("Collab db is not initialized"))?;
let read = db.read_txn();
let workspace_id = workspace_id.to_string();
let object_id = object_id.to_string();
Ok(read.is_exist(user_id, &workspace_id, &object_id))
}
}
#[async_trait]
@ -101,9 +159,13 @@ impl UserStatusCallback for UserStatusCallbackImpl {
user_workspace,
device_id
);
let workspace_id = user_workspace.workspace_id()?;
let data_source = self
.folder_init_data_source(user_id, &workspace_id, auth_type)
.await?;
self
.folder_manager
.initialize_after_sign_in(user_id)
.initialize_after_sign_in(user_id, data_source)
.await?;
self
.database_manager
@ -135,37 +197,9 @@ impl UserStatusCallback for UserStatusCallbackImpl {
device_id
);
let workspace_id = user_workspace.workspace_id()?;
// In the current implementation, when a user signs up for AppFlowy Cloud, a default workspace
// is automatically created for them. However, for users who sign up through Supabase, the creation
// of the default workspace relies on the client-side operation. This means that the process
// for initializing a default workspace differs depending on the sign-up method used.
let data_source = match self
.folder_manager
.cloud_service
.get_folder_doc_state(
&workspace_id,
user_profile.uid,
CollabType::Folder,
&workspace_id,
)
.await
{
Ok(doc_state) => match auth_type {
AuthType::Local => FolderInitDataSource::LocalDisk {
create_if_not_exist: true,
},
AuthType::AppFlowyCloud => FolderInitDataSource::Cloud(doc_state),
},
Err(err) => match auth_type {
AuthType::Local => FolderInitDataSource::LocalDisk {
create_if_not_exist: true,
},
AuthType::AppFlowyCloud => {
return Err(err);
},
},
};
let data_source = self
.folder_init_data_source(user_profile.uid, &workspace_id, auth_type)
.await?;
self
.folder_manager
@ -204,12 +238,17 @@ impl UserStatusCallback for UserStatusCallbackImpl {
async fn on_workspace_opened(
&self,
user_id: i64,
user_workspace: &UserWorkspace,
workspace_id: &Uuid,
_user_workspace: &UserWorkspace,
auth_type: &AuthType,
) -> FlowyResult<()> {
let data_source = self
.folder_init_data_source(user_id, workspace_id, auth_type)
.await?;
self
.folder_manager
.initialize_after_open_workspace(user_id)
.initialize_after_open_workspace(user_id, data_source)
.await?;
self
.database_manager
@ -221,11 +260,11 @@ impl UserStatusCallback for UserStatusCallbackImpl {
.await?;
self
.ai_manager
.initialize_after_open_workspace(&user_workspace.id)
.initialize_after_open_workspace(workspace_id)
.await?;
self
.storage_manager
.initialize_after_open_workspace(&user_workspace.id)
.initialize_after_open_workspace(workspace_id)
.await;
Ok(())
}

View file

@ -14,6 +14,7 @@ collab-plugins = { workspace = true }
collab-integrate = { workspace = true }
flowy-folder-pub = { workspace = true }
flowy-search-pub = { workspace = true }
flowy-user-pub = { workspace = true }
flowy-sqlite = { workspace = true }
flowy-derive.workspace = true
flowy-notification = { workspace = true }

View file

@ -262,16 +262,17 @@ impl FolderManager {
/// Initialize the folder with the given workspace id.
/// Fetch the folder updates from the cloud service and initialize the folder.
#[tracing::instrument(skip(self, user_id), err)]
pub async fn initialize_after_sign_in(&self, user_id: i64) -> FlowyResult<()> {
#[tracing::instrument(skip_all, err)]
pub async fn initialize_after_sign_in(
&self,
user_id: i64,
data_source: FolderInitDataSource,
) -> FlowyResult<()> {
let workspace_id = self.user.workspace_id()?;
let object_id = &workspace_id;
let is_exist = self
.user
.is_folder_exist_on_disk(user_id, &workspace_id)
.unwrap_or(false);
if is_exist {
if let Err(err) = self.initialize(user_id, &workspace_id, data_source).await {
// If failed to open folder with remote data, open from local disk. After open from the local
// disk. the data will be synced to the remote server.
error!("initialize folder with error {:?}, fallback local", err);
self
.initialize(
user_id,
@ -281,39 +282,17 @@ impl FolderManager {
},
)
.await?;
} else {
let folder_doc_state = self
.cloud_service
.get_folder_doc_state(&workspace_id, user_id, CollabType::Folder, object_id)
.await?;
if let Err(err) = self
.initialize(
user_id,
&workspace_id,
FolderInitDataSource::Cloud(folder_doc_state),
)
.await
{
// If failed to open folder with remote data, open from local disk. After open from the local
// disk. the data will be synced to the remote server.
error!("initialize folder with error {:?}, fallback local", err);
self
.initialize(
user_id,
&workspace_id,
FolderInitDataSource::LocalDisk {
create_if_not_exist: false,
},
)
.await?;
}
}
Ok(())
}
pub async fn initialize_after_open_workspace(&self, uid: i64) -> FlowyResult<()> {
self.initialize_after_sign_in(uid).await
pub async fn initialize_after_open_workspace(
&self,
uid: i64,
data_source: FolderInitDataSource,
) -> FlowyResult<()> {
self.initialize_after_sign_in(uid, data_source).await
}
/// Initialize the folder for the new user.
@ -2139,6 +2118,7 @@ pub(crate) fn get_workspace_private_view_pbs(workspace_id: &Uuid, folder: &Folde
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum FolderInitDataSource {
/// It means using the data stored on local disk to initialize the folder
LocalDisk { create_if_not_exist: bool },

View file

@ -85,9 +85,7 @@ impl FolderCloudService for LocalServerFolderCloudServiceImpl {
} else {
let data = default_encode_collab_for_collab_type(uid, &object_id, collab_type).await?;
drop(read_txn);
// create default folder doc
Err(FlowyError::local_version_not_support())
Ok(data.doc_state.to_vec())
}
}

View file

@ -181,7 +181,7 @@ impl StorageManager {
}
}
pub async fn initialize_after_open_workspace(&self, workspace_id: &str) {
pub async fn initialize_after_open_workspace(&self, workspace_id: &Uuid) {
self.enable_storage_write_access();
if let Err(err) = prepare_upload_task(self.uploader.clone(), self.user_service.clone()).await {

View file

@ -1,13 +1,13 @@
use client_api::entity::billing_dto::SubscriptionPlan;
use std::sync::Weak;
use strum_macros::Display;
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
use flowy_error::FlowyResult;
use flowy_user_pub::cloud::UserCloudConfig;
use flowy_user_pub::entities::*;
use lib_dispatch::prelude::*;
use lib_infra::async_trait::async_trait;
use std::sync::Weak;
use strum_macros::Display;
use uuid::Uuid;
use crate::event_handler::*;
use crate::user_manager::UserManager;
@ -323,6 +323,7 @@ pub trait UserStatusCallback: Send + Sync + 'static {
async fn on_workspace_opened(
&self,
_user_id: i64,
_workspace_id: &Uuid,
_user_workspace: &UserWorkspace,
_auth_type: &AuthType,
) -> FlowyResult<()> {

View file

@ -195,7 +195,7 @@ impl UserManager {
.user_status_callback
.read()
.await
.on_workspace_opened(uid, &user_workspace, &user_profile.auth_type)
.on_workspace_opened(uid, workspace_id, &user_workspace, &user_profile.auth_type)
.await
{
error!("Open workspace failed: {:?}", err);