mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-04-24 14:47:13 -04:00
chore: pass folder init data
This commit is contained in:
parent
791a79a234
commit
92d5690bba
10 changed files with 106 additions and 85 deletions
1
frontend/rust-lib/Cargo.lock
generated
1
frontend/rust-lib/Cargo.lock
generated
|
@ -2835,6 +2835,7 @@ dependencies = [
|
||||||
"flowy-notification",
|
"flowy-notification",
|
||||||
"flowy-search-pub",
|
"flowy-search-pub",
|
||||||
"flowy-sqlite",
|
"flowy-sqlite",
|
||||||
|
"flowy-user-pub",
|
||||||
"futures",
|
"futures",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lib-dispatch",
|
"lib-dispatch",
|
||||||
|
|
|
@ -131,7 +131,7 @@ impl AIManager {
|
||||||
#[instrument(skip_all, err)]
|
#[instrument(skip_all, err)]
|
||||||
pub async fn initialize_after_open_workspace(
|
pub async fn initialize_after_open_workspace(
|
||||||
&self,
|
&self,
|
||||||
_workspace_id: &str,
|
_workspace_id: &Uuid,
|
||||||
) -> Result<(), FlowyError> {
|
) -> Result<(), FlowyError> {
|
||||||
let local_ai = self.local_ai.clone();
|
let local_ai = self.local_ai.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
|
|
@ -253,6 +253,7 @@ impl AppFlowyCore {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let user_status_callback = UserStatusCallbackImpl {
|
let user_status_callback = UserStatusCallbackImpl {
|
||||||
|
user_manager: user_manager.clone(),
|
||||||
collab_builder,
|
collab_builder,
|
||||||
folder_manager: folder_manager.clone(),
|
folder_manager: folder_manager.clone(),
|
||||||
database_manager: database_manager.clone(),
|
database_manager: database_manager.clone(),
|
||||||
|
|
|
@ -4,23 +4,27 @@ use anyhow::Context;
|
||||||
use client_api::entity::billing_dto::SubscriptionPlan;
|
use client_api::entity::billing_dto::SubscriptionPlan;
|
||||||
use tracing::{error, event, info};
|
use tracing::{error, event, info};
|
||||||
|
|
||||||
|
use crate::server_layer::ServerProvider;
|
||||||
use collab_entity::CollabType;
|
use collab_entity::CollabType;
|
||||||
use collab_integrate::collab_builder::AppFlowyCollabBuilder;
|
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_ai::ai_manager::AIManager;
|
||||||
use flowy_database2::DatabaseManager;
|
use flowy_database2::DatabaseManager;
|
||||||
use flowy_document::manager::DocumentManager;
|
use flowy_document::manager::DocumentManager;
|
||||||
use flowy_error::FlowyResult;
|
use flowy_error::{FlowyError, FlowyResult};
|
||||||
use flowy_folder::manager::{FolderInitDataSource, FolderManager};
|
use flowy_folder::manager::{FolderInitDataSource, FolderManager};
|
||||||
use flowy_storage::manager::StorageManager;
|
use flowy_storage::manager::StorageManager;
|
||||||
use flowy_user::event_map::UserStatusCallback;
|
use flowy_user::event_map::UserStatusCallback;
|
||||||
|
use flowy_user::user_manager::UserManager;
|
||||||
use flowy_user_pub::cloud::{UserCloudConfig, UserCloudServiceProvider};
|
use flowy_user_pub::cloud::{UserCloudConfig, UserCloudServiceProvider};
|
||||||
use flowy_user_pub::entities::{AuthType, UserProfile, UserWorkspace};
|
use flowy_user_pub::entities::{AuthType, UserProfile, UserWorkspace};
|
||||||
use lib_dispatch::runtime::AFPluginRuntime;
|
use lib_dispatch::runtime::AFPluginRuntime;
|
||||||
use lib_infra::async_trait::async_trait;
|
use lib_infra::async_trait::async_trait;
|
||||||
|
use uuid::Uuid;
|
||||||
use crate::server_layer::ServerProvider;
|
|
||||||
|
|
||||||
pub(crate) struct UserStatusCallbackImpl {
|
pub(crate) struct UserStatusCallbackImpl {
|
||||||
|
pub(crate) user_manager: Arc<UserManager>,
|
||||||
pub(crate) collab_builder: Arc<AppFlowyCollabBuilder>,
|
pub(crate) collab_builder: Arc<AppFlowyCollabBuilder>,
|
||||||
pub(crate) folder_manager: Arc<FolderManager>,
|
pub(crate) folder_manager: Arc<FolderManager>,
|
||||||
pub(crate) database_manager: Arc<DatabaseManager>,
|
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]
|
#[async_trait]
|
||||||
|
@ -101,9 +159,13 @@ impl UserStatusCallback for UserStatusCallbackImpl {
|
||||||
user_workspace,
|
user_workspace,
|
||||||
device_id
|
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
|
self
|
||||||
.folder_manager
|
.folder_manager
|
||||||
.initialize_after_sign_in(user_id)
|
.initialize_after_sign_in(user_id, data_source)
|
||||||
.await?;
|
.await?;
|
||||||
self
|
self
|
||||||
.database_manager
|
.database_manager
|
||||||
|
@ -135,37 +197,9 @@ impl UserStatusCallback for UserStatusCallbackImpl {
|
||||||
device_id
|
device_id
|
||||||
);
|
);
|
||||||
let workspace_id = user_workspace.workspace_id()?;
|
let workspace_id = user_workspace.workspace_id()?;
|
||||||
|
let data_source = self
|
||||||
// In the current implementation, when a user signs up for AppFlowy Cloud, a default workspace
|
.folder_init_data_source(user_profile.uid, &workspace_id, auth_type)
|
||||||
// is automatically created for them. However, for users who sign up through Supabase, the creation
|
.await?;
|
||||||
// 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);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
self
|
self
|
||||||
.folder_manager
|
.folder_manager
|
||||||
|
@ -204,12 +238,17 @@ impl UserStatusCallback for UserStatusCallbackImpl {
|
||||||
async fn on_workspace_opened(
|
async fn on_workspace_opened(
|
||||||
&self,
|
&self,
|
||||||
user_id: i64,
|
user_id: i64,
|
||||||
user_workspace: &UserWorkspace,
|
workspace_id: &Uuid,
|
||||||
|
_user_workspace: &UserWorkspace,
|
||||||
auth_type: &AuthType,
|
auth_type: &AuthType,
|
||||||
) -> FlowyResult<()> {
|
) -> FlowyResult<()> {
|
||||||
|
let data_source = self
|
||||||
|
.folder_init_data_source(user_id, workspace_id, auth_type)
|
||||||
|
.await?;
|
||||||
|
|
||||||
self
|
self
|
||||||
.folder_manager
|
.folder_manager
|
||||||
.initialize_after_open_workspace(user_id)
|
.initialize_after_open_workspace(user_id, data_source)
|
||||||
.await?;
|
.await?;
|
||||||
self
|
self
|
||||||
.database_manager
|
.database_manager
|
||||||
|
@ -221,11 +260,11 @@ impl UserStatusCallback for UserStatusCallbackImpl {
|
||||||
.await?;
|
.await?;
|
||||||
self
|
self
|
||||||
.ai_manager
|
.ai_manager
|
||||||
.initialize_after_open_workspace(&user_workspace.id)
|
.initialize_after_open_workspace(workspace_id)
|
||||||
.await?;
|
.await?;
|
||||||
self
|
self
|
||||||
.storage_manager
|
.storage_manager
|
||||||
.initialize_after_open_workspace(&user_workspace.id)
|
.initialize_after_open_workspace(workspace_id)
|
||||||
.await;
|
.await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ collab-plugins = { workspace = true }
|
||||||
collab-integrate = { workspace = true }
|
collab-integrate = { workspace = true }
|
||||||
flowy-folder-pub = { workspace = true }
|
flowy-folder-pub = { workspace = true }
|
||||||
flowy-search-pub = { workspace = true }
|
flowy-search-pub = { workspace = true }
|
||||||
|
flowy-user-pub = { workspace = true }
|
||||||
flowy-sqlite = { workspace = true }
|
flowy-sqlite = { workspace = true }
|
||||||
flowy-derive.workspace = true
|
flowy-derive.workspace = true
|
||||||
flowy-notification = { workspace = true }
|
flowy-notification = { workspace = true }
|
||||||
|
|
|
@ -262,16 +262,17 @@ impl FolderManager {
|
||||||
|
|
||||||
/// Initialize the folder with the given workspace id.
|
/// Initialize the folder with the given workspace id.
|
||||||
/// Fetch the folder updates from the cloud service and initialize the folder.
|
/// Fetch the folder updates from the cloud service and initialize the folder.
|
||||||
#[tracing::instrument(skip(self, user_id), err)]
|
#[tracing::instrument(skip_all, err)]
|
||||||
pub async fn initialize_after_sign_in(&self, user_id: i64) -> FlowyResult<()> {
|
pub async fn initialize_after_sign_in(
|
||||||
|
&self,
|
||||||
|
user_id: i64,
|
||||||
|
data_source: FolderInitDataSource,
|
||||||
|
) -> FlowyResult<()> {
|
||||||
let workspace_id = self.user.workspace_id()?;
|
let workspace_id = self.user.workspace_id()?;
|
||||||
let object_id = &workspace_id;
|
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
|
||||||
let is_exist = self
|
// disk. the data will be synced to the remote server.
|
||||||
.user
|
error!("initialize folder with error {:?}, fallback local", err);
|
||||||
.is_folder_exist_on_disk(user_id, &workspace_id)
|
|
||||||
.unwrap_or(false);
|
|
||||||
if is_exist {
|
|
||||||
self
|
self
|
||||||
.initialize(
|
.initialize(
|
||||||
user_id,
|
user_id,
|
||||||
|
@ -281,39 +282,17 @@ impl FolderManager {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn initialize_after_open_workspace(&self, uid: i64) -> FlowyResult<()> {
|
pub async fn initialize_after_open_workspace(
|
||||||
self.initialize_after_sign_in(uid).await
|
&self,
|
||||||
|
uid: i64,
|
||||||
|
data_source: FolderInitDataSource,
|
||||||
|
) -> FlowyResult<()> {
|
||||||
|
self.initialize_after_sign_in(uid, data_source).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize the folder for the new user.
|
/// 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)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum FolderInitDataSource {
|
pub enum FolderInitDataSource {
|
||||||
/// It means using the data stored on local disk to initialize the folder
|
/// It means using the data stored on local disk to initialize the folder
|
||||||
LocalDisk { create_if_not_exist: bool },
|
LocalDisk { create_if_not_exist: bool },
|
||||||
|
|
|
@ -85,9 +85,7 @@ impl FolderCloudService for LocalServerFolderCloudServiceImpl {
|
||||||
} else {
|
} else {
|
||||||
let data = default_encode_collab_for_collab_type(uid, &object_id, collab_type).await?;
|
let data = default_encode_collab_for_collab_type(uid, &object_id, collab_type).await?;
|
||||||
drop(read_txn);
|
drop(read_txn);
|
||||||
|
Ok(data.doc_state.to_vec())
|
||||||
// create default folder doc
|
|
||||||
Err(FlowyError::local_version_not_support())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
self.enable_storage_write_access();
|
||||||
|
|
||||||
if let Err(err) = prepare_upload_task(self.uploader.clone(), self.user_service.clone()).await {
|
if let Err(err) = prepare_upload_task(self.uploader.clone(), self.user_service.clone()).await {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use client_api::entity::billing_dto::SubscriptionPlan;
|
use client_api::entity::billing_dto::SubscriptionPlan;
|
||||||
use std::sync::Weak;
|
|
||||||
use strum_macros::Display;
|
|
||||||
|
|
||||||
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
|
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
|
||||||
use flowy_error::FlowyResult;
|
use flowy_error::FlowyResult;
|
||||||
use flowy_user_pub::cloud::UserCloudConfig;
|
use flowy_user_pub::cloud::UserCloudConfig;
|
||||||
use flowy_user_pub::entities::*;
|
use flowy_user_pub::entities::*;
|
||||||
use lib_dispatch::prelude::*;
|
use lib_dispatch::prelude::*;
|
||||||
use lib_infra::async_trait::async_trait;
|
use lib_infra::async_trait::async_trait;
|
||||||
|
use std::sync::Weak;
|
||||||
|
use strum_macros::Display;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::event_handler::*;
|
use crate::event_handler::*;
|
||||||
use crate::user_manager::UserManager;
|
use crate::user_manager::UserManager;
|
||||||
|
@ -323,6 +323,7 @@ pub trait UserStatusCallback: Send + Sync + 'static {
|
||||||
async fn on_workspace_opened(
|
async fn on_workspace_opened(
|
||||||
&self,
|
&self,
|
||||||
_user_id: i64,
|
_user_id: i64,
|
||||||
|
_workspace_id: &Uuid,
|
||||||
_user_workspace: &UserWorkspace,
|
_user_workspace: &UserWorkspace,
|
||||||
_auth_type: &AuthType,
|
_auth_type: &AuthType,
|
||||||
) -> FlowyResult<()> {
|
) -> FlowyResult<()> {
|
||||||
|
|
|
@ -195,7 +195,7 @@ impl UserManager {
|
||||||
.user_status_callback
|
.user_status_callback
|
||||||
.read()
|
.read()
|
||||||
.await
|
.await
|
||||||
.on_workspace_opened(uid, &user_workspace, &user_profile.auth_type)
|
.on_workspace_opened(uid, workspace_id, &user_workspace, &user_profile.auth_type)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
error!("Open workspace failed: {:?}", err);
|
error!("Open workspace failed: {:?}", err);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue