mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-08-06 16:02:17 +00:00

* fix: migrate cloud document when the document content is not sync to local * chore: clippy
91 lines
3.1 KiB
Rust
91 lines
3.1 KiB
Rust
use std::sync::Arc;
|
|
|
|
use collab::core::collab::MutexCollab;
|
|
use collab::core::origin::{CollabClient, CollabOrigin};
|
|
use collab_document::document::Document;
|
|
use collab_document::document_data::default_document_data;
|
|
use collab_folder::{Folder, View};
|
|
use tracing::{event, instrument};
|
|
|
|
use collab_integrate::{PersistenceError, RocksCollabDB, YrsDocAction};
|
|
use flowy_error::{internal_error, FlowyError, FlowyResult};
|
|
use flowy_user_deps::entities::Authenticator;
|
|
|
|
use crate::migrations::migration::UserDataMigration;
|
|
use crate::migrations::util::load_collab;
|
|
use crate::services::entities::Session;
|
|
|
|
/// Migrate the first level documents of the workspace by inserting documents
|
|
pub struct HistoricalEmptyDocumentMigration;
|
|
|
|
impl UserDataMigration for HistoricalEmptyDocumentMigration {
|
|
fn name(&self) -> &str {
|
|
"historical_empty_document"
|
|
}
|
|
|
|
#[instrument(name = "HistoricalEmptyDocumentMigration", skip_all, err)]
|
|
fn run(
|
|
&self,
|
|
session: &Session,
|
|
collab_db: &Arc<RocksCollabDB>,
|
|
authenticator: &Authenticator,
|
|
) -> FlowyResult<()> {
|
|
// - The `empty document` struct has already undergone refactoring prior to the launch of the AppFlowy cloud version.
|
|
// - Consequently, if a user is utilizing the AppFlowy cloud version, there is no need to perform any migration for the `empty document` struct.
|
|
// - This migration step is only necessary for users who are transitioning from a local version of AppFlowy to the cloud version.
|
|
if !matches!(authenticator, Authenticator::Local) {
|
|
return Ok(());
|
|
}
|
|
let write_txn = collab_db.write_txn();
|
|
let origin = CollabOrigin::Client(CollabClient::new(session.user_id, "phantom"));
|
|
let folder_collab = match load_collab(session.user_id, &write_txn, &session.user_workspace.id) {
|
|
Ok(fc) => fc,
|
|
Err(_) => return Ok(()),
|
|
};
|
|
|
|
let folder = Folder::open(session.user_id, folder_collab, None)?;
|
|
let migration_views = folder.get_workspace_views();
|
|
|
|
// For historical reasons, the first level documents are empty. So migrate them by inserting
|
|
// the default document data.
|
|
for view in migration_views {
|
|
if migrate_empty_document(&write_txn, &origin, &view, session.user_id).is_err() {
|
|
event!(
|
|
tracing::Level::ERROR,
|
|
"Failed to migrate document {}",
|
|
view.id
|
|
);
|
|
}
|
|
}
|
|
|
|
write_txn.commit_transaction().map_err(internal_error)?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
fn migrate_empty_document<'a, W>(
|
|
write_txn: &W,
|
|
origin: &CollabOrigin,
|
|
view: &View,
|
|
user_id: i64,
|
|
) -> Result<(), FlowyError>
|
|
where
|
|
W: YrsDocAction<'a>,
|
|
PersistenceError: From<W::Error>,
|
|
{
|
|
// If the document is not exist, we don't need to migrate it.
|
|
if load_collab(user_id, write_txn, &view.id).is_err() {
|
|
let collab = Arc::new(MutexCollab::new(origin.clone(), &view.id, vec![]));
|
|
let document = Document::create_with_data(collab, default_document_data())?;
|
|
let encode = document.get_collab().encode_collab_v1();
|
|
write_txn.flush_doc_with(user_id, &view.id, &encode.doc_state, &encode.state_vector)?;
|
|
event!(
|
|
tracing::Level::INFO,
|
|
"Did migrate empty document {}",
|
|
view.id
|
|
);
|
|
}
|
|
|
|
Ok(())
|
|
}
|