123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- use crate::manager::FolderId;
- use crate::{
- event_map::WorkspaceDatabase,
- services::persistence::{AppTableSql, TrashTableSql, ViewTableSql, WorkspaceTableSql},
- };
- use flowy_database::kv::KV;
- use flowy_error::{FlowyError, FlowyResult};
- use flowy_folder_data_model::revision::{AppRevision, FolderRevision, ViewRevision, WorkspaceRevision};
- use flowy_revision::disk::SQLiteTextBlockRevisionPersistence;
- use flowy_revision::reset::{RevisionResettable, RevisionStructReset};
- use flowy_sync::client_folder::make_folder_rev_json_str;
- use flowy_sync::entities::revision::Revision;
- use flowy_sync::{client_folder::FolderPad, entities::revision::md5};
- use std::sync::Arc;
- const V1_MIGRATION: &str = "FOLDER_V1_MIGRATION";
- const V2_MIGRATION: &str = "FOLDER_V2_MIGRATION";
- #[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));
- if KV::get_bool(&key) {
- return Ok(None);
- }
- 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() {
- 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);
- tracing::trace!("Run folder v1 migration");
- Ok(Some(folder))
- }
- pub async fn run_v2_migration(&self, folder_id: &FolderId) -> FlowyResult<()> {
- let key = md5(format!("{}{}", self.user_id, V2_MIGRATION));
- if KV::get_bool(&key) {
- return Ok(());
- }
- 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(());
- }
- let _ = self.migration_folder_rev_struct_if_need(folder_id).await?;
- KV::set_bool(&key, true);
- tracing::trace!("Run folder v3 migration");
- Ok(())
- }
- 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(),
- };
- 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> {
- let pad = FolderPad::from_revisions(revisions)?;
- 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)
- }
- }
|