use indexed_db_futures::{
Build, error::OpenDbError, query_source::QuerySource, transaction::TransactionMode,
};
use matrix_sdk_crypto::olm::InboundGroupSession;
use tracing::{debug, info};
use wasm_bindgen::JsValue;
use crate::{
IndexeddbCryptoStoreError,
crypto_store::{
InboundGroupSessionIndexedDbObject, Result, keys,
migrations::{
MigrationDb, add_nonunique_index, do_schema_upgrade, old_keys,
v7::InboundGroupSessionIndexedDbObject2,
},
},
serializer::SafeEncodeSerializer,
};
pub(crate) async fn schema_add(name: &str) -> Result<(), OpenDbError> {
do_schema_upgrade(name, 9, |tx, _| {
let db = tx.db();
let object_store = db.create_object_store(keys::INBOUND_GROUP_SESSIONS_V3).build()?;
add_nonunique_index(
&object_store,
keys::INBOUND_GROUP_SESSIONS_BACKUP_INDEX,
"needs_backup",
)?;
add_nonunique_index(
&object_store,
keys::INBOUND_GROUP_SESSIONS_BACKED_UP_TO_INDEX,
"backed_up_to",
)?;
Ok(())
})
.await
}
pub(crate) async fn data_migrate(name: &str, serializer: &SafeEncodeSerializer) -> Result<()> {
let db = MigrationDb::new(name, 10).await?;
let txn = db
.transaction([old_keys::INBOUND_GROUP_SESSIONS_V2, keys::INBOUND_GROUP_SESSIONS_V3])
.with_mode(TransactionMode::Readwrite)
.build()?;
let inbound_group_sessions2 = txn.object_store(old_keys::INBOUND_GROUP_SESSIONS_V2)?;
let inbound_group_sessions3 = txn.object_store(keys::INBOUND_GROUP_SESSIONS_V3)?;
let row_count = inbound_group_sessions2.count().await?;
info!(row_count, "Shrinking inbound_group_session records");
if let Some(mut cursor) = inbound_group_sessions2.open_cursor().await? {
let mut idx = 0;
while let Some(value) = cursor.next_record::<JsValue>().await? {
idx += 1;
if idx % 100 == 0 {
debug!("Migrating session {idx} of {row_count}");
}
let old_value: InboundGroupSessionIndexedDbObject2 =
serde_wasm_bindgen::from_value(value)?;
let session = InboundGroupSession::from_pickle(
serializer.deserialize_value_from_bytes(&old_value.pickled_session)?,
)
.map_err(|e| IndexeddbCryptoStoreError::CryptoStoreError(e.into()))?;
let new_key = serializer.encode_key(
keys::INBOUND_GROUP_SESSIONS_V3,
(&session.room_id, session.session_id()),
);
let new_value =
InboundGroupSessionIndexedDbObject::from_session(&session, serializer).await?;
inbound_group_sessions3
.add(&serde_wasm_bindgen::to_value(&new_value)?)
.with_key(new_key)
.build()?;
cursor.delete()?;
}
debug!("Migrated {idx} sessions.");
}
inbound_group_sessions2.clear()?.await?;
txn.commit().await?;
Ok(())
}
pub(crate) async fn schema_delete(name: &str) -> Result<(), OpenDbError> {
do_schema_upgrade(name, 10, |tx, _| {
tx.db().delete_object_store(old_keys::INBOUND_GROUP_SESSIONS_V2)?;
Ok(())
})
.await
}