use indexed_db_futures::{
Build, error::OpenDbError, query_source::QuerySource, transaction::TransactionMode,
};
use matrix_sdk_crypto::store::types::RoomKeyWithheldEntry;
use tracing::{debug, info, warn};
use wasm_bindgen::JsValue;
use super::{MigrationDb, old_keys};
use crate::{
crypto_store::{Result, keys, migrations::do_schema_upgrade},
serializer::SafeEncodeSerializer,
};
pub(crate) async fn schema_add(name: &str) -> Result<(), OpenDbError> {
do_schema_upgrade(name, 100, |tx, _| {
tx.db().create_object_store(keys::WITHHELD_SESSIONS).build()?;
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::DIRECT_WITHHELD_INFO, keys::WITHHELD_SESSIONS])
.with_mode(TransactionMode::Readwrite)
.build()?;
let old_store = txn.object_store(old_keys::DIRECT_WITHHELD_INFO)?;
let new_store = txn.object_store(keys::WITHHELD_SESSIONS)?;
let row_count = old_store.count().await?;
info!(row_count, "Migrating withheld_sessions data");
if let Some(mut cursor) = old_store.open_cursor().await? {
let mut idx = 0;
while let Some(value) = cursor.next_record::<JsValue>().await? {
idx += 1;
if idx % 100 == 0 {
debug!("Migrating withheld session {idx} of {row_count}");
}
let deserialized: RoomKeyWithheldEntry = serializer.deserialize_value(value.clone())?;
if let (Some(room_id), Some(session_id)) =
(deserialized.content.room_id(), deserialized.content.megolm_session_id())
{
let new_key = serializer.encode_key(keys::WITHHELD_SESSIONS, (room_id, session_id));
new_store.add(&value).with_key(new_key).build()?;
} else {
warn!(
"Discarding withheld session with unknown room/session ID: {:?}",
deserialized
);
}
cursor.delete()?;
}
debug!("Migrated {idx} withheld sessions.");
}
txn.commit().await?;
Ok(())
}
pub(crate) async fn schema_delete(name: &str) -> Result<(), OpenDbError> {
do_schema_upgrade(name, 101, |tx, _| {
tx.db().delete_object_store(old_keys::DIRECT_WITHHELD_INFO)?;
Ok(())
})
.await
}