Skip to content

Commit 098aacf

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 098aacf

File tree

3 files changed

+64
-0
lines changed

3 files changed

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

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)