diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs index 095070594..e0205c85e 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs @@ -34,42 +34,37 @@ pub async fn open_and_upgrade_db( name: &str, serializer: &IndexeddbSerializer, ) -> Result { - // This is all a bit of a hack. Some of the version migrations require a data - // migration, which has to be done via async APIs; however, the - // JS `upgrade_needed` mechanism does not allow for async calls. + // Move the DB version up from where it is to the latest version. // - // Start by finding out what the existing version is, if any. + // Schema changes need to be separate from data migrations, so we often + // have a pattern of: + // + // 1. schema_add - create new object stores, indices etc. + // 2. data_migrate - move data from the old stores to the new ones + // 3. schema_delete - delete any now-unused stores etc. + // + // Migrations like these require the schema version to be bumped twice, + // because of the separate "add" and "delete" stages. + let old_version = db_version(name).await?; - // Perform the schema-only migrations if old_version < 5 { v0_to_v5::migrate_schema_up_to_v5(name).await?; } - // If we have yet to complete the migration to V7, migrate the schema to V6 - // (if necessary), and then migrate any remaining data. if old_version < 6 { v5_to_v7::migrate_schema_up_to_v6(name).await?; } if old_version < 7 { v5_to_v7::prepare_data_for_v7(name, serializer).await?; - - // Now we can safely complete the migration to V7 which will drop the old store. v5_to_v7::migrate_schema_for_v7(name).await?; } - // Migrate to v8, keeping the same schema but fixing the keys in - // inbound_group_sessions2 if old_version < 8 { v7_to_v8::prepare_data_for_v8(name, serializer).await?; v7_to_v8::migrate_schema_for_v8(name).await?; } - // Migrate to v10, moving from inbound_group_sessions2 to - // inbound_group_sessions3, which has smaller values by storing JavaScript - // objects instead of serialized arrays, and base64 strings instead of - // arrays of ints. inbound_group_sessions3 also has backed_up_to, which is - // indexed. if old_version < 9 { v8_to_v10::upgrade_scheme_to_v9_create_inbound_group_sessions3(name).await?; } @@ -79,8 +74,7 @@ pub async fn open_and_upgrade_db( v8_to_v10::upgrade_scheme_to_v10_delete_inbound_group_sessions2(name).await?; } - // We know we've upgraded to v10 now, so we can open the DB at that version and - // return it + // Open and return the DB (we know it's at the latest version) Ok(IdbDatabase::open_u32(name, 10)?.await?) } diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v0_to_v5.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v0_to_v5.rs index 8ef0e364b..36234b3df 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v0_to_v5.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v0_to_v5.rs @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Schema-only migrations adding various stores and indices, notably +//! the first version of `inbound_group_sessions`. + use indexed_db_futures::{IdbDatabase, IdbKeyPath}; use web_sys::{DomException, IdbIndexParameters}; @@ -21,6 +24,7 @@ use crate::crypto_store::{ Result, }; +/// Perform schema migrations as needed, up to schema version 5. pub(crate) async fn migrate_schema_up_to_v5(name: &str) -> Result<(), DomException> { do_schema_upgrade(name, 5, |db, old_version| { // An old_version of 1 could either mean actually the first version of the diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v5_to_v7.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v5_to_v7.rs index 61e905472..cc43fdca7 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v5_to_v7.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v5_to_v7.rs @@ -34,6 +34,7 @@ use crate::{ IndexeddbCryptoStoreError, }; +/// Perform the schema upgrade v5 to v6, creating `inbound_group_sessions2`. pub(crate) async fn migrate_schema_up_to_v6(name: &str) -> Result<(), DomException> { do_schema_upgrade(name, 6, |db, _| { let object_store = db.create_object_store(old_keys::INBOUND_GROUP_SESSIONS_V2)?; @@ -51,6 +52,7 @@ pub(crate) async fn migrate_schema_up_to_v6(name: &str) -> Result<(), DomExcepti .await } +/// Migrate data from `inbound_group_sessions` into `inbound_group_sessions2`. pub(crate) async fn prepare_data_for_v7( name: &str, serializer: &IndexeddbSerializer, @@ -118,6 +120,7 @@ async fn do_prepare_data_for_v7(serializer: &IndexeddbSerializer, db: &IdbDataba Ok(txn.await.into_result()?) } +/// Perform the schema upgrade v6 to v7, deleting `inbound_group_sessions`. pub(crate) async fn migrate_schema_for_v7(name: &str) -> Result<(), DomException> { do_schema_upgrade(name, 7, |db, _| { db.delete_object_store(old_keys::INBOUND_GROUP_SESSIONS_V1)?; diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v7.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v7.rs index 62a1b4a6d..05631e798 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v7.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v7.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Structs and keys used for reading/writing objects in schema v7 + /// The objects we store in the inbound_group_sessions2 indexeddb object /// store (in schemas v7 and v8) #[derive(Debug, serde::Serialize, serde::Deserialize)] diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v7_to_v8.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v7_to_v8.rs index bf5b3374a..7ec0b4447 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v7_to_v8.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v7_to_v8.rs @@ -29,15 +29,14 @@ use crate::{ IndexeddbCryptoStoreError, }; +/// In the migration v5 to v7, we incorrectly copied the keys in +/// `inbound_group_sessions` verbatim into `inbound_group_sessions2`. What we +/// should have done is re-hash them using the new table name, so we fix them up +/// here. pub(crate) async fn prepare_data_for_v8( name: &str, serializer: &IndexeddbSerializer, ) -> Result<()> { - // In prepare_data_for_v6, we incorrectly copied the keys in - // inbound_group_sessions verbatim into inbound_group_sessions2. What we - // should have done is re-hash them using the new table name, so we fix - // them up here. - info!("IndexeddbCryptoStore upgrade data -> v8 starting"); let db = IdbDatabase::open(name)?.await?; @@ -119,6 +118,7 @@ pub(crate) async fn prepare_data_for_v8( Ok(()) } +/// Perform the schema upgrade v7 to v8, Just bumping the schema version. pub(crate) async fn migrate_schema_for_v8(name: &str) -> Result<(), DomException> { do_schema_upgrade(name, 8, |_, _| { // Just bump the version number to 8 to demonstrate that we have run the data diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v8_to_v10.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v8_to_v10.rs index 6056d8d9a..72d6642a1 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v8_to_v10.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v8_to_v10.rs @@ -14,10 +14,6 @@ //! Migration code that moves from inbound_group_sessions2 to //! inbound_group_sessions3, shrinking the values stored in each record. -//! -//! The migration 8->9 creates the new store inbound_group_sessions3. -//! Then we move the data into the new store. -//! The migration 9->10 deletes the old store inbound_group_sessions2. use indexed_db_futures::{ idb_object_store::IdbObjectStore, IdbDatabase, IdbIndex, IdbKeyPath, IdbQuerySource, @@ -46,6 +42,7 @@ fn add_nonunique_index<'a>( object_store.create_index_with_params(name, &IdbKeyPath::str(key_path), ¶ms) } +/// Perform the schema upgrade v8 to v9, creating `inbound_group_sessions3`. pub(crate) async fn upgrade_scheme_to_v9_create_inbound_group_sessions3( name: &str, ) -> Result<(), DomException> { @@ -72,6 +69,7 @@ pub(crate) async fn upgrade_scheme_to_v9_create_inbound_group_sessions3( .await } +/// Migrate data from `inbound_group_sessions2` into `inbound_group_sessions3`. pub(crate) async fn migrate_data_before_v10_populate_inbound_group_sessions3( name: &str, serializer: &IndexeddbSerializer, @@ -141,6 +139,7 @@ pub(crate) async fn migrate_data_before_v10_populate_inbound_group_sessions3( Ok(()) } +/// Perform the schema upgrade v8 to v10, deleting `inbound_group_sessions2`. pub(crate) async fn upgrade_scheme_to_v10_delete_inbound_group_sessions2( name: &str, ) -> Result<(), DomException> {