Skip to content

Commit

Permalink
update old/new versions handle, remove unused code
Browse files Browse the repository at this point in the history
  • Loading branch information
laruh committed Oct 11, 2024
1 parent 7511d94 commit 14bef0d
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 122 deletions.
3 changes: 2 additions & 1 deletion mm2src/coins/nft/storage/sql_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,7 @@ impl NftTransferHistoryStorageOps for AsyncMutexGuard<'_, AsyncConnection> {
if history_table_exists.is_none() {
return Ok(false);
}
// if history table exists, then we need to check its schema version
if schema_versions_table_exists.is_none() {
conn.execute(&create_schema_versions_sql()?, []).map(|_| ())?;
}
Expand All @@ -1081,7 +1082,7 @@ impl NftTransferHistoryStorageOps for AsyncMutexGuard<'_, AsyncConnection> {
.unwrap_or(0);

if version < CURRENT_SCHEMA_VERSION_TX_HISTORY {
// Call migration function to update the table schema to the latest version
// update history table schema to the latest version
migrate_tx_history_table_to_schema_v2(conn, history_table, schema_table)?;
}

Expand Down
7 changes: 3 additions & 4 deletions mm2src/coins/nft/storage/wasm/nft_idb.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::nft::storage::wasm::wasm_storage::{LastScannedBlockTable, NftListTable, NftMigrationTable,
NftTransferHistoryTable};
use crate::nft::storage::wasm::wasm_storage::{LastScannedBlockTable, NftListTable, NftTransferHistoryTable};
use async_trait::async_trait;
use mm2_db::indexed_db::InitDbResult;
use mm2_db::indexed_db::{DbIdentifier, DbInstance, DbLocked, IndexedDb, IndexedDbBuilder};

const DB_VERSION: u32 = 2; // TODO need to set it as 2, as we need to change prim key in NftTransferHistoryTable
/// prim key was changed in NftTransferHistoryTable, schemas of the other tables remain the same.
const DB_VERSION: u32 = 2;

/// Represents a locked instance of the `NftCacheIDB` database.
///
Expand Down Expand Up @@ -32,7 +32,6 @@ impl DbInstance for NftCacheIDB {
.with_table::<NftListTable>()
.with_table::<NftTransferHistoryTable>()
.with_table::<LastScannedBlockTable>()
.with_table::<NftMigrationTable>()
.build()
.await?;
Ok(NftCacheIDB { inner })
Expand Down
148 changes: 31 additions & 117 deletions mm2src/coins/nft/storage/wasm/wasm_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ use crate::nft::storage::{get_offset_limit, NftListStorageOps, NftTokenAddrId, N
NftTransferHistoryStorageOps, RemoveNftResult};
use async_trait::async_trait;
use ethereum_types::Address;
use mm2_db::indexed_db::{BeBigUint, DbTable, DbUpgrader, MultiIndex, OnUpgradeError, OnUpgradeResult, TableSignature};
use mm2_db::indexed_db::{BeBigUint, DbTable, DbUpgrader, MultiIndex, OnUpgradeResult, TableSignature};
use mm2_err_handle::map_to_mm::MapToMmResult;
use mm2_err_handle::prelude::MmError;
use mm2_err_handle::prelude::MmResult;
use mm2_number::BigUint;
use num_traits::ToPrimitive;
Expand Down Expand Up @@ -907,27 +906,28 @@ impl NftListTable {
impl TableSignature for NftListTable {
const TABLE_NAME: &'static str = "nft_list_cache_table";

fn on_upgrade_needed(upgrader: &DbUpgrader, old_version: u32, new_version: u32) -> OnUpgradeResult<()> {
if old_version == 0 && new_version == 2 {
let table = upgrader.create_table(Self::TABLE_NAME)?;
table.create_multi_index(
CHAIN_TOKEN_ADD_TOKEN_ID_INDEX,
&["chain", "token_address", "token_id"],
true,
)?;
table.create_multi_index(CHAIN_BLOCK_NUMBER_INDEX, &["chain", "block_number"], false)?;
table.create_multi_index(CHAIN_TOKEN_ADD_INDEX, &["chain", "token_address"], false)?;
table.create_multi_index(CHAIN_TOKEN_DOMAIN_INDEX, &["chain", "token_domain"], false)?;
table.create_multi_index(CHAIN_IMAGE_DOMAIN_INDEX, &["chain", "image_domain"], false)?;
table.create_multi_index(
Self::CHAIN_ANIMATION_DOMAIN_INDEX,
&["chain", "animation_domain"],
false,
)?;
table.create_multi_index(Self::CHAIN_EXTERNAL_DOMAIN_INDEX, &["chain", "external_domain"], false)?;
table.create_index("chain", false)?;
table.create_index("block_number", false)?;
fn on_upgrade_needed(upgrader: &DbUpgrader, old_version: u32, _new_version: u32) -> OnUpgradeResult<()> {
if old_version > 0 {
return Ok(());
}
let table = upgrader.create_table(Self::TABLE_NAME)?;
table.create_multi_index(
CHAIN_TOKEN_ADD_TOKEN_ID_INDEX,
&["chain", "token_address", "token_id"],
true,
)?;
table.create_multi_index(CHAIN_BLOCK_NUMBER_INDEX, &["chain", "block_number"], false)?;
table.create_multi_index(CHAIN_TOKEN_ADD_INDEX, &["chain", "token_address"], false)?;
table.create_multi_index(CHAIN_TOKEN_DOMAIN_INDEX, &["chain", "token_domain"], false)?;
table.create_multi_index(CHAIN_IMAGE_DOMAIN_INDEX, &["chain", "image_domain"], false)?;
table.create_multi_index(
Self::CHAIN_ANIMATION_DOMAIN_INDEX,
&["chain", "animation_domain"],
false,
)?;
table.create_multi_index(Self::CHAIN_EXTERNAL_DOMAIN_INDEX, &["chain", "external_domain"], false)?;
table.create_index("chain", false)?;
table.create_index("block_number", false)?;
Ok(())
}
}
Expand Down Expand Up @@ -957,9 +957,9 @@ pub(crate) struct NftTransferHistoryTable {

impl NftTransferHistoryTable {
// old prim key index for DB_VERSION = 1
const _CHAIN_TX_HASH_LOG_INDEX_INDEX: &'static str = "chain_tx_hash_log_index_index";
const CHAIN_TX_HASH_LOG_INDEX_INDEX: &'static str = "chain_tx_hash_log_index_index";
// prim key multi index for DB_VERSION = 2
const CHAIN_TX_HASH_LOG_INDEX_TOKEN_ID_INDEX: &'static str = "chain_tx_hash_log_index_token_idindex";
const CHAIN_TX_HASH_LOG_INDEX_TOKEN_ID_INDEX: &'static str = "chain_tx_hash_log_index_token_id_index";

fn from_transfer_history(transfer: &NftTransferHistory) -> WasmNftCacheResult<NftTransferHistoryTable> {
let details_json =
Expand Down Expand Up @@ -1013,11 +1013,13 @@ impl TableSignature for NftTransferHistoryTable {
table.create_index("chain", false)?;
} else if old_version == 1 && new_version == 2 {
let table = upgrader.open_table(Self::TABLE_NAME)?;
// When we change indexes during `onupgradeneeded`, IndexedDB automatically updates it with the existing records
table.create_multi_index(
Self::CHAIN_TX_HASH_LOG_INDEX_TOKEN_ID_INDEX,
&["chain", "transaction_hash", "log_index", "token_id"],
true,
)?;
table.delete_index(Self::CHAIN_TX_HASH_LOG_INDEX_INDEX)?;
}
Ok(())
}
Expand All @@ -1032,11 +1034,12 @@ pub(crate) struct LastScannedBlockTable {
impl TableSignature for LastScannedBlockTable {
const TABLE_NAME: &'static str = "last_scanned_block_table";

fn on_upgrade_needed(upgrader: &DbUpgrader, old_version: u32, new_version: u32) -> OnUpgradeResult<()> {
if old_version == 0 && new_version == 2 {
let table = upgrader.create_table(Self::TABLE_NAME)?;
table.create_index("chain", true)?;
fn on_upgrade_needed(upgrader: &DbUpgrader, old_version: u32, _new_version: u32) -> OnUpgradeResult<()> {
if old_version > 0 {
return Ok(());
}
let table = upgrader.create_table(Self::TABLE_NAME)?;
table.create_index("chain", true)?;
Ok(())
}
}
Expand All @@ -1048,92 +1051,3 @@ fn nft_details_from_item(item: NftListTable) -> WasmNftCacheResult<Nft> {
fn transfer_details_from_item(item: NftTransferHistoryTable) -> WasmNftCacheResult<NftTransferHistory> {
json::from_value(item.details_json).map_to_mm(|e| WasmNftCacheError::ErrorDeserializing(e.to_string()))
}

#[derive(Deserialize, Serialize)]
pub(crate) struct NftMigrationTable {
tx_history_migration: u32,
}

impl TableSignature for NftMigrationTable {
const TABLE_NAME: &'static str = "nft_migration";

fn on_upgrade_needed(upgrader: &DbUpgrader, mut old_version: u32, new_version: u32) -> OnUpgradeResult<()> {
while old_version < new_version {
match old_version {
0 => {
// do nothing explicitly
},
1 => {
// this step covers both cases of (old version, new version): (0, 2) and (1, 2)
let table = upgrader.create_table(Self::TABLE_NAME)?;
table.create_index("tx_history_migration", true)?;
},
unsupported_version => {
return MmError::err(OnUpgradeError::UnsupportedVersion {
unsupported_version,
old_version,
new_version,
})
},
}

old_version += 1;
}
Ok(())
}
}

#[async_trait]
trait TxHistoryMigrationOps {
async fn current_tx_history_migration(&self) -> WasmNftCacheResult<u32>;

async fn migrate_tx_history_data(&self) -> WasmNftCacheResult<()>;
}

#[async_trait]
impl TxHistoryMigrationOps for NftCacheIDBLocked<'_> {
async fn current_tx_history_migration(&self) -> WasmNftCacheResult<u32> {
let db_transaction = self.get_inner().transaction().await?;
let table = db_transaction.table::<NftMigrationTable>().await?;
let maybe_item = table
.cursor_builder()
.bound("tx_history_migration", 0, u32::MAX)
.reverse()
.where_first()
.open_cursor("tx_history_migration")
.await
.map_err(|e| WasmNftCacheError::OpenCursorError(e.to_string()))?
.next()
.await
.map_err(|e| WasmNftCacheError::GetItemError(e.to_string()))?;
Ok(maybe_item
.map(|(_item_id, item)| item.tx_history_migration)
.unwrap_or(0))
}

async fn migrate_tx_history_data(&self) -> WasmNftCacheResult<()> {
let db_transaction = self.get_inner().transaction().await?;
let migration_table = db_transaction.table::<NftMigrationTable>().await?;

let mut migration = self.current_tx_history_migration().await?;
loop {
match migration {
0 => {
let _tx_history_table = db_transaction.table::<NftTransferHistoryTable>().await?;

},
1 => break,
unsupported => {
return MmError::err(WasmNftCacheError::InternalError(format!(
"Unsupported migration version: {}",
unsupported
)))
},
}
migration += 1;
migration_table.add_item(&NftMigrationTable {tx_history_migration: migration}).await?;
}

Ok(())
}
}
16 changes: 16 additions & 0 deletions mm2src/mm2_db/src/indexed_db/drivers/upgrader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub enum OnUpgradeError {
old_version: u32,
new_version: u32,
},
#[display(fmt = "Error occurred due to deleting the '{}' index: {}", index, description)]
ErrorDeletingIndex { index: String, description: String },
}

pub struct DbUpgrader {
Expand Down Expand Up @@ -108,4 +110,18 @@ impl TableUpgrader {
description: stringify_js_error(&e),
})
}

/// Deletes an index.
/// Regardless of whether the index is created using one or multiple fields, the deleteIndex()
/// method is used to delete any type of index, and it works in the same way for both.
/// https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/deleteIndex
pub fn delete_index(&self, index: &str) -> OnUpgradeResult<()> {
self.object_store
.delete_index(index)
.map(|_| ())
.map_to_mm(|e| OnUpgradeError::ErrorDeletingIndex {
index: index.to_owned(),
description: stringify_js_error(&e),
})
}
}

0 comments on commit 14bef0d

Please sign in to comment.