Skip to content

Commit 629a09a

Browse files
chore(wasm/keystore): add helper to open a migration connection/transaction
We cannot use the regular `Database::open()` because this would result in infinite recursion when used in migrations.
1 parent 58fc5d1 commit 629a09a

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
use idb::builder::DatabaseBuilder;
2+
3+
use crate::{
4+
CryptoKeystoreError, CryptoKeystoreResult, Database, DatabaseKey,
5+
connection::{
6+
KeystoreDatabaseConnection, TransactionWrapper, platform::wasm::WasmStorageWrapper,
7+
storage::WasmEncryptedStorage,
8+
},
9+
};
10+
11+
impl Database {
12+
pub(crate) async fn migration_connection(
13+
previous_builder: DatabaseBuilder,
14+
key: &DatabaseKey,
15+
) -> CryptoKeystoreResult<KeystoreDatabaseConnection> {
16+
let idb_during_migration = previous_builder.build().await?;
17+
let wrapper_during_migration = WasmStorageWrapper::Persistent(idb_during_migration);
18+
let storage_during_migration = WasmEncryptedStorage::new(key, wrapper_during_migration);
19+
Ok(KeystoreDatabaseConnection::from_inner(storage_during_migration))
20+
}
21+
22+
/// Open an idb store with a transaction during a migration, do some generic work on the transaction, commit the
23+
/// transaction and close the store.
24+
///
25+
/// Make sure you haven't got an open connection before calling this.
26+
pub(crate) async fn migration_transaction<F>(
27+
db_during_migration: KeystoreDatabaseConnection,
28+
migration_work: F,
29+
) -> CryptoKeystoreResult<()>
30+
where
31+
F: AsyncFnOnce(&mut TransactionWrapper) -> CryptoKeystoreResult<()>,
32+
{
33+
let idb = match db_during_migration.storage().storage {
34+
WasmStorageWrapper::Persistent(ref database) => database,
35+
WasmStorageWrapper::InMemory(_) => {
36+
return Err(CryptoKeystoreError::MigrationFailed(
37+
"In-memory keystore doesn't support migrations".into(),
38+
));
39+
}
40+
};
41+
let stores = idb.store_names();
42+
let mut conn = db_during_migration.conn().await;
43+
let mut transaction = conn.new_transaction(&stores).await?;
44+
45+
migration_work(&mut transaction).await?;
46+
47+
let result = transaction.commit_tx().await;
48+
db_during_migration.close().await?;
49+
if result.is_err() {
50+
return Err(CryptoKeystoreError::MigrationFailed(
51+
"Migration transaction hasn't been cmmitted".into(),
52+
));
53+
}
54+
Ok(())
55+
}
56+
}

keystore/src/connection/platform/wasm/migrations/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod db_key_type_to_bytes;
22
mod delete_credential_by_value;
3+
mod migration_connection;
34
mod pre_v4;
45
mod v0;
56
mod v2;

keystore/src/connection/platform/wasm/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ impl WasmConnection {
5454

5555
Ok(())
5656
}
57+
58+
/// Only for use during migrations.
59+
pub(crate) fn from_inner(inner: WasmEncryptedStorage) -> Self {
60+
Self {
61+
name: None,
62+
conn: inner,
63+
}
64+
}
5765
}
5866

5967
impl DatabaseConnectionRequirements for WasmConnection {}

0 commit comments

Comments
 (0)