migration.rs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. use crate::manager::FolderId;
  2. use crate::{
  3. event_map::WorkspaceDatabase,
  4. services::persistence::{AppTableSql, TrashTableSql, ViewTableSql, WorkspaceTableSql},
  5. };
  6. use bytes::Bytes;
  7. use flowy_database::kv::KV;
  8. use flowy_error::{FlowyError, FlowyResult};
  9. use flowy_folder_data_model::revision::{AppRevision, FolderRevision, ViewRevision, WorkspaceRevision};
  10. use flowy_revision::reset::{RevisionResettable, RevisionStructReset};
  11. use flowy_sync::client_folder::make_folder_rev_json_str;
  12. use flowy_sync::client_folder::FolderPad;
  13. use flowy_sync::entities::revision::Revision;
  14. use flowy_sync::server_folder::FolderOperationsBuilder;
  15. use crate::services::persistence::rev_sqlite::SQLiteFolderRevisionPersistence;
  16. use flowy_sync::util::md5;
  17. use std::sync::Arc;
  18. const V1_MIGRATION: &str = "FOLDER_V1_MIGRATION";
  19. const V2_MIGRATION: &str = "FOLDER_V2_MIGRATION";
  20. #[allow(dead_code)]
  21. const V3_MIGRATION: &str = "FOLDER_V3_MIGRATION";
  22. pub(crate) struct FolderMigration {
  23. user_id: String,
  24. database: Arc<dyn WorkspaceDatabase>,
  25. }
  26. impl FolderMigration {
  27. pub fn new(user_id: &str, database: Arc<dyn WorkspaceDatabase>) -> Self {
  28. Self {
  29. user_id: user_id.to_owned(),
  30. database,
  31. }
  32. }
  33. pub fn run_v1_migration(&self) -> FlowyResult<Option<FolderPad>> {
  34. let key = migration_flag_key(&self.user_id, V1_MIGRATION);
  35. if KV::get_bool(&key) {
  36. return Ok(None);
  37. }
  38. let pool = self.database.db_pool()?;
  39. let conn = &*pool.get()?;
  40. let workspaces = conn.immediate_transaction::<_, FlowyError, _>(|| {
  41. let mut workspaces = WorkspaceTableSql::read_workspaces(&self.user_id, None, conn)?
  42. .into_iter()
  43. .map(WorkspaceRevision::from)
  44. .collect::<Vec<_>>();
  45. for workspace in workspaces.iter_mut() {
  46. let mut apps = AppTableSql::read_workspace_apps(&workspace.id, conn)?
  47. .into_iter()
  48. .map(AppRevision::from)
  49. .collect::<Vec<_>>();
  50. for app in apps.iter_mut() {
  51. let views = ViewTableSql::read_views(&app.id, conn)?
  52. .into_iter()
  53. .map(ViewRevision::from)
  54. .collect::<Vec<_>>();
  55. app.belongings = views;
  56. }
  57. workspace.apps = apps;
  58. }
  59. Ok(workspaces)
  60. })?;
  61. if workspaces.is_empty() {
  62. tracing::trace!("Run folder v1 migration, but workspace is empty");
  63. KV::set_bool(&key, true);
  64. return Ok(None);
  65. }
  66. let trash = conn.immediate_transaction::<_, FlowyError, _>(|| {
  67. let trash = TrashTableSql::read_all(conn)?;
  68. Ok(trash)
  69. })?;
  70. let folder = FolderPad::new(workspaces, trash)?;
  71. KV::set_bool(&key, true);
  72. tracing::info!("Run folder v1 migration");
  73. Ok(Some(folder))
  74. }
  75. pub async fn run_v2_migration(&self, folder_id: &FolderId) -> FlowyResult<()> {
  76. let key = migration_flag_key(&self.user_id, V2_MIGRATION);
  77. if KV::get_bool(&key) {
  78. return Ok(());
  79. }
  80. let _ = self.migration_folder_rev_struct(folder_id).await?;
  81. KV::set_bool(&key, true);
  82. // tracing::info!("Run folder v2 migration");
  83. Ok(())
  84. }
  85. pub async fn run_v3_migration(&self, folder_id: &FolderId) -> FlowyResult<()> {
  86. let key = migration_flag_key(&self.user_id, V3_MIGRATION);
  87. if KV::get_bool(&key) {
  88. return Ok(());
  89. }
  90. let _ = self.migration_folder_rev_struct(folder_id).await?;
  91. KV::set_bool(&key, true);
  92. tracing::trace!("Run folder v3 migration");
  93. Ok(())
  94. }
  95. pub async fn migration_folder_rev_struct(&self, folder_id: &FolderId) -> FlowyResult<()> {
  96. let object = FolderRevisionResettable {
  97. folder_id: folder_id.as_ref().to_owned(),
  98. };
  99. let pool = self.database.db_pool()?;
  100. let disk_cache = SQLiteFolderRevisionPersistence::new(&self.user_id, pool);
  101. let reset = RevisionStructReset::new(&self.user_id, object, Arc::new(disk_cache));
  102. reset.run().await
  103. }
  104. }
  105. fn migration_flag_key(user_id: &str, version: &str) -> String {
  106. md5(format!("{}{}", user_id, version,))
  107. }
  108. pub struct FolderRevisionResettable {
  109. folder_id: String,
  110. }
  111. impl RevisionResettable for FolderRevisionResettable {
  112. fn target_id(&self) -> &str {
  113. &self.folder_id
  114. }
  115. fn reset_data(&self, revisions: Vec<Revision>) -> FlowyResult<Bytes> {
  116. let pad = FolderPad::from_revisions(revisions)?;
  117. let json = pad.to_json()?;
  118. let bytes = FolderOperationsBuilder::new().insert(&json).build().json_bytes();
  119. Ok(bytes)
  120. }
  121. fn default_target_rev_str(&self) -> FlowyResult<String> {
  122. let folder = FolderRevision::default();
  123. let json = make_folder_rev_json_str(&folder)?;
  124. Ok(json)
  125. }
  126. fn read_record(&self) -> Option<String> {
  127. KV::get_str(self.target_id())
  128. }
  129. fn set_record(&self, record: String) {
  130. KV::set_str(self.target_id(), record);
  131. }
  132. }