143 lines
4.7 KiB
Rust
Raw Normal View History

use crate::manager::FolderId;
use crate::{
2022-01-30 10:33:21 +08:00
event_map::WorkspaceDatabase,
2022-01-20 23:51:11 +08:00
services::persistence::{AppTableSql, TrashTableSql, ViewTableSql, WorkspaceTableSql},
};
use flowy_database::kv::KV;
use flowy_error::{FlowyError, FlowyResult};
2022-08-16 11:24:37 +08:00
use flowy_folder_data_model::revision::{AppRevision, FolderRevision, ViewRevision, WorkspaceRevision};
2022-03-19 16:52:28 +08:00
use flowy_revision::disk::SQLiteTextBlockRevisionPersistence;
2022-08-16 11:24:37 +08:00
use flowy_revision::reset::{RevisionResettable, RevisionStructReset};
use flowy_sync::client_folder::make_folder_rev_json_str;
use flowy_sync::entities::revision::Revision;
2022-03-19 16:52:28 +08:00
use flowy_sync::{client_folder::FolderPad, entities::revision::md5};
2022-08-16 11:24:37 +08:00
use std::sync::Arc;
2022-03-01 23:38:26 +08:00
const V1_MIGRATION: &str = "FOLDER_V1_MIGRATION";
const V2_MIGRATION: &str = "FOLDER_V2_MIGRATION";
2022-08-16 11:24:37 +08:00
#[allow(dead_code)]
const V3_MIGRATION: &str = "FOLDER_V3_MIGRATION";
pub(crate) struct FolderMigration {
user_id: String,
database: Arc<dyn WorkspaceDatabase>,
}
impl FolderMigration {
pub fn new(user_id: &str, database: Arc<dyn WorkspaceDatabase>) -> Self {
Self {
user_id: user_id.to_owned(),
database,
}
}
pub fn run_v1_migration(&self) -> FlowyResult<Option<FolderPad>> {
let key = md5(format!("{}{}", self.user_id, V1_MIGRATION));
2022-01-28 10:56:55 +08:00
if KV::get_bool(&key) {
return Ok(None);
}
2022-03-01 23:38:26 +08:00
let pool = self.database.db_pool()?;
let conn = &*pool.get()?;
let workspaces = conn.immediate_transaction::<_, FlowyError, _>(|| {
let mut workspaces = WorkspaceTableSql::read_workspaces(&self.user_id, None, conn)?
.into_iter()
.map(WorkspaceRevision::from)
.collect::<Vec<_>>();
for workspace in workspaces.iter_mut() {
let mut apps = AppTableSql::read_workspace_apps(&workspace.id, conn)?
.into_iter()
.map(AppRevision::from)
.collect::<Vec<_>>();
for app in apps.iter_mut() {
let views = ViewTableSql::read_views(&app.id, conn)?
.into_iter()
.map(ViewRevision::from)
.collect::<Vec<_>>();
app.belongings = views;
}
workspace.apps = apps;
}
Ok(workspaces)
})?;
if workspaces.is_empty() {
2022-03-01 23:38:26 +08:00
tracing::trace!("Run folder v1 migration, but workspace is empty");
KV::set_bool(&key, true);
return Ok(None);
}
let trash = conn.immediate_transaction::<_, FlowyError, _>(|| {
let trash = TrashTableSql::read_all(conn)?;
Ok(trash)
})?;
let folder = FolderPad::new(workspaces, trash)?;
KV::set_bool(&key, true);
2022-03-01 23:38:26 +08:00
tracing::trace!("Run folder v1 migration");
Ok(Some(folder))
}
2022-03-01 23:38:26 +08:00
2022-08-16 11:24:37 +08:00
pub async fn run_v2_migration(&self, folder_id: &FolderId) -> FlowyResult<()> {
2022-03-01 23:38:26 +08:00
let key = md5(format!("{}{}", self.user_id, V2_MIGRATION));
if KV::get_bool(&key) {
2022-08-16 11:24:37 +08:00
return Ok(());
2022-03-01 23:38:26 +08:00
}
2022-08-16 11:24:37 +08:00
let _ = self.migration_folder_rev_struct_if_need(folder_id).await?;
KV::set_bool(&key, true);
tracing::trace!("Run folder v2 migration");
Ok(())
}
#[allow(dead_code)]
pub async fn run_v3_migration(&self, folder_id: &FolderId) -> FlowyResult<()> {
let key = md5(format!("{}{}", self.user_id, V3_MIGRATION));
if KV::get_bool(&key) {
return Ok(());
2022-03-01 23:38:26 +08:00
}
2022-08-16 11:24:37 +08:00
let _ = self.migration_folder_rev_struct_if_need(folder_id).await?;
KV::set_bool(&key, true);
tracing::trace!("Run folder v3 migration");
Ok(())
}
2022-03-01 23:38:26 +08:00
2022-08-16 11:24:37 +08:00
pub async fn migration_folder_rev_struct_if_need(&self, folder_id: &FolderId) -> FlowyResult<()> {
let object = FolderRevisionResettable {
folder_id: folder_id.as_ref().to_owned(),
};
2022-03-01 23:38:26 +08:00
2022-08-16 11:24:37 +08:00
let pool = self.database.db_pool()?;
let disk_cache = SQLiteTextBlockRevisionPersistence::new(&self.user_id, pool);
let reset = RevisionStructReset::new(&self.user_id, object, Arc::new(disk_cache));
reset.run().await
}
}
pub struct FolderRevisionResettable {
folder_id: String,
}
impl RevisionResettable for FolderRevisionResettable {
fn target_id(&self) -> &str {
&self.folder_id
}
fn target_reset_rev_str(&self, revisions: Vec<Revision>) -> FlowyResult<String> {
2022-03-01 23:38:26 +08:00
let pad = FolderPad::from_revisions(revisions)?;
2022-08-16 11:24:37 +08:00
let json = pad.to_json()?;
Ok(json)
}
fn default_target_rev_str(&self) -> FlowyResult<String> {
let folder = FolderRevision::default();
let json = make_folder_rev_json_str(&folder)?;
Ok(json)
2022-03-01 23:38:26 +08:00
}
}