diff --git a/mm2src/coins/lp_coins.rs b/mm2src/coins/lp_coins.rs index 1626e9d8af..c689e833d3 100644 --- a/mm2src/coins/lp_coins.rs +++ b/mm2src/coins/lp_coins.rs @@ -3500,7 +3500,7 @@ pub trait MmCoin: SwapOps + WatcherOps + MarketCoinOps + Send + Sync + 'static { // BCH cash address format has colon after prefix, e.g. bitcoincash: // Colon can't be used in file names on Windows so it should be escaped let my_address = my_address.replace(':', "_"); - ctx.dbdir() + ctx.address_dir(&my_address) .join("TRANSACTIONS") .join(format!("{}_{}.json", self.ticker(), my_address)) } @@ -3512,7 +3512,7 @@ pub trait MmCoin: SwapOps + WatcherOps + MarketCoinOps + Send + Sync + 'static { // BCH cash address format has colon after prefix, e.g. bitcoincash: // Colon can't be used in file names on Windows so it should be escaped let my_address = my_address.replace(':', "_"); - ctx.dbdir() + ctx.address_dir(&my_address) .join("TRANSACTIONS") .join(format!("{}_{}_migration", self.ticker(), my_address)) } @@ -5781,6 +5781,9 @@ where let fut = async move { let fs_fut = async { + mm2_io::fs::create_parents_async(&migration_path) + .await + .map_err(|e| e.into_inner())?; let mut file = fs::File::create(&tmp_file).await?; file.write_all(&migration_number.to_le_bytes()).await?; file.flush().await?; @@ -5805,28 +5808,15 @@ where T: MmCoin + MarketCoinOps + ?Sized, { let history_path = coin.tx_history_path(ctx); - let tmp_file = format!("{}.tmp", history_path.display()); - history.sort_unstable_by(compare_transaction_details); let fut = async move { - let content = json::to_vec(&history).map_to_mm(|e| TxHistoryError::ErrorSerializing(e.to_string()))?; - - let fs_fut = async { - let mut file = fs::File::create(&tmp_file).await?; - file.write_all(&content).await?; - file.flush().await?; - fs::rename(&tmp_file, &history_path).await?; - Ok(()) - }; - - let res: io::Result<_> = fs_fut.await; - if let Err(e) = res { - let error = format!("Error '{}' creating/writing/renaming the tmp file {}", e, tmp_file); - return MmError::err(TxHistoryError::ErrorSaving(error)); - } + mm2_io::fs::write_json(&history, &history_path, true) + .await + .mm_err(|e| TxHistoryError::ErrorSaving(e.to_string()))?; Ok(()) }; + Box::new(fut.boxed().compat()) } diff --git a/mm2src/mm2_core/src/mm_ctx.rs b/mm2src/mm2_core/src/mm_ctx.rs index e159298c49..723d93e3f5 100644 --- a/mm2src/mm2_core/src/mm_ctx.rs +++ b/mm2src/mm2_core/src/mm_ctx.rs @@ -132,6 +132,12 @@ pub struct MmCtx { /// The DB connection to the global DB hosting common data (e.g. stats) and other data needed for correctly bootstrapping on restarts. #[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))] pub global_db_conn: OnceLock>>, + /// The DB connection to the global DB hosting common data (e.g. stats) and other data needed for correctly bootstrapping on restarts. + /// + /// This is the same DB as `self.global_db_conn` but made available via an asynchronous interface. + /// Use this if favor of `self.global_db_conn` for new implementations. + #[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))] + pub async_global_db_conn: OnceLock>>, /// The DB connection to the wallet DB the KDF instance will use for current execution. /// /// The wallet DB path is based on the seed that KDF is initialized with. An initialization with different seed will use a different wallet DB. @@ -205,6 +211,8 @@ impl MmCtx { #[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))] global_db_conn: OnceLock::default(), #[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))] + async_global_db_conn: OnceLock::default(), + #[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))] wallet_db_conn: OnceLock::default(), #[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))] async_wallet_db_conn: OnceLock::default(), @@ -386,6 +394,8 @@ impl MmCtx { if cfg!(not(feature = "new-db-arch")) { return self.dbdir(); } + // Colon can't be used in file names on Windows so it should be escaped. + let address = address.replace(':', "_"); self.db_root().join("addresses").join(address) } @@ -393,6 +403,14 @@ impl MmCtx { #[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))] pub fn global_db(&self) -> MutexGuard { self.global_db_conn.get().unwrap().lock().unwrap() } + /// Returns an AsyncSQL connection to the global database. + /// + /// This replaces `self.global_db()` and should be used for new implementations. + #[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))] + pub async fn async_global_db(&self) -> Arc> { + self.async_global_db_conn.get().unwrap().clone() + } + /// Returns a SQL connection to the shared wallet database. /// /// For new implementations, use `self.async_wallet_db()` instead. @@ -478,6 +496,9 @@ impl MmCtx { #[cfg(all(feature = "new-db-arch", not(target_arch = "wasm32")))] pub async fn init_global_and_wallet_db(&self) -> Result<(), String> { let global_db = Connection::open(self.global_dir().join("global.db")).map_err(|e| e.to_string())?; + let async_global_db = AsyncConnection::open(self.global_dir().join("global.db")) + .await + .map_err(|e| e.to_string())?; let wallet_db = Connection::open(self.wallet_dir().join("wallet.db")).map_err(|e| e.to_string())?; let async_wallet_db = AsyncConnection::open(self.wallet_dir().join("wallet.db")) .await @@ -485,6 +506,9 @@ impl MmCtx { self.global_db_conn .set(Arc::new(Mutex::new(global_db))) .map_err(|_| "Global DB already set".to_string())?; + self.async_global_db_conn + .set(Arc::new(AsyncMutex::new(async_global_db))) + .map_err(|_| "Async Global DB already set".to_string())?; self.wallet_db_conn .set(Arc::new(Mutex::new(wallet_db))) .map_err(|_| "Wallet DB already set".to_string())?; @@ -530,11 +554,6 @@ impl MmCtx { Ok(()) } - #[cfg(not(target_arch = "wasm32"))] - pub fn sqlite_conn_opt(&self) -> Option> { - self.sqlite_connection.get().map(|conn| conn.lock().unwrap()) - } - #[cfg(not(target_arch = "wasm32"))] pub fn sqlite_connection(&self) -> MutexGuard { self.sqlite_connection @@ -576,6 +595,16 @@ pub enum AddressDataError { SqliteConnectionFailure(db_common::sqlite::rusqlite::Error), } +#[cfg(not(target_arch = "wasm32"))] +impl From for String { + fn from(err: AddressDataError) -> Self { + match err { + AddressDataError::CreateAddressDirFailure(e) => format!("Failed to create address directory: {}", e), + AddressDataError::SqliteConnectionFailure(e) => format!("Failed to open SQLite connection: {}", e), + } + } +} + /// Returns the path to the MM database root. /// /// Path priority: diff --git a/mm2src/mm2_main/src/database/global.rs b/mm2src/mm2_main/src/database/global.rs new file mode 100644 index 0000000000..d41a5245be --- /dev/null +++ b/mm2src/mm2_main/src/database/global.rs @@ -0,0 +1,75 @@ +use db_common::{async_sql_conn::AsyncConnError, + sqlite::{query_single_row, rusqlite::params}}; +use derive_more::Display; +use mm2_core::mm_ctx::MmArc; +use uuid::Uuid; + +// TODO: Let's let this table be called `ongoing_swaps` and remove the `is_finished` column. +// And we might also add a new table `completed_swaps` that hold a copy of all the completed swaps for all the coins. +const INIT_GLOBAL_DB_TABLES: &str = " + CREATE TABLE IF NOT EXISTS swaps ( + uuid VARCHAR(255) PRIMARY KEY, + maker_address VARCHAR(255) NOT NULL + ); +"; +const SELECT_ADDRESS_FOR_SWAP_UUID: &str = "SELECT maker_address FROM swaps WHERE uuid = ?1"; +const INSERT_SWAP: &str = "INSERT INTO swaps (uuid, maker_address) VALUES (?1, ?2)"; + +/// Errors that can occur when interacting with the global database. +#[derive(Debug, Display)] +pub enum GlobalDBError { + SqlError(AsyncConnError), +} + +impl From for String { + fn from(err: GlobalDBError) -> Self { + match err { + GlobalDBError::SqlError(e) => format!("SQL error: {}", e), + } + } +} + +impl From for GlobalDBError { + fn from(err: AsyncConnError) -> Self { GlobalDBError::SqlError(err) } +} + +/// Initializes the global database with the necessary tables. +pub async fn init_global_db(ctx: &MmArc) -> Result<(), GlobalDBError> { + let conn = ctx.async_global_db().await; + conn.lock() + .await + .call(|conn| conn.execute_batch(INIT_GLOBAL_DB_TABLES).map_err(|e| e.into())) + .await?; + Ok(()) +} + +/// Gets the maker address for a given swap UUID from the global database. +/// +/// Returns `Ok(Some(addr))` if the UUID is found, `Ok(None)` if the UUID is not found, and `Err(e)` if there was an error. +pub async fn get_maker_address_for_swap_uuid(ctx: &MmArc, uuid: &Uuid) -> Result, GlobalDBError> { + let conn = ctx.async_global_db().await; + let uuid = uuid.to_string(); + let address: Option = conn + .lock() + .await + .call(move |conn| { + query_single_row(conn, SELECT_ADDRESS_FOR_SWAP_UUID, params![uuid], |row| row.get(0)).map_err(|e| e.into()) + }) + .await?; + Ok(address) +} + +/// Inserts a new swap handle (uuid and maker address pair) into the global database. +pub async fn insert_swap_in_global_db(ctx: &MmArc, uuid: &Uuid, maker_address: &str) -> Result<(), GlobalDBError> { + let conn = ctx.async_global_db().await; + let uuid = uuid.to_string(); + let maker_address = maker_address.to_string(); + conn.lock() + .await + .call(move |conn| { + conn.execute(INSERT_SWAP, params![uuid, maker_address]) + .map_err(|e| e.into()) + }) + .await?; + Ok(()) +} diff --git a/mm2src/mm2_main/src/database.rs b/mm2src/mm2_main/src/database/mod.rs similarity index 99% rename from mm2src/mm2_main/src/database.rs rename to mm2src/mm2_main/src/database/mod.rs index 6945204643..2bebca2a1d 100644 --- a/mm2src/mm2_main/src/database.rs +++ b/mm2src/mm2_main/src/database/mod.rs @@ -1,5 +1,7 @@ /// The module responsible to work with SQLite database /// +#[cfg(feature = "new-db-arch")] +pub mod global; pub mod my_orders; pub mod my_swaps; pub mod stats_nodes; diff --git a/mm2src/mm2_main/src/database/my_swaps.rs b/mm2src/mm2_main/src/database/my_swaps.rs index 3f68b3b689..60d9cfa394 100644 --- a/mm2src/mm2_main/src/database/my_swaps.rs +++ b/mm2src/mm2_main/src/database/my_swaps.rs @@ -68,7 +68,7 @@ const INSERT_MY_SWAP: &str = "INSERT INTO my_swaps (my_coin, other_coin, uuid, started_at, swap_type) VALUES (?1, ?2, ?3, ?4, ?5)"; pub fn insert_new_swap( - ctx: &MmArc, + conn: &Connection, my_coin: &str, other_coin: &str, uuid: &str, @@ -76,7 +76,6 @@ pub fn insert_new_swap( swap_type: u8, ) -> SqlResult<()> { debug!("Inserting new swap {} to the SQLite database", uuid); - let conn = ctx.sqlite_connection(); let params = [my_coin, other_coin, uuid, started_at, &swap_type.to_string()]; conn.execute(INSERT_MY_SWAP, params).map(|_| ()) } diff --git a/mm2src/mm2_main/src/lp_native_dex.rs b/mm2src/mm2_main/src/lp_native_dex.rs index 3600370ffc..ecb9de55ed 100644 --- a/mm2src/mm2_main/src/lp_native_dex.rs +++ b/mm2src/mm2_main/src/lp_native_dex.rs @@ -18,6 +18,8 @@ // marketmaker // +#[cfg(all(not(target_arch = "wasm32"), feature = "new-db-arch"))] +use crate::database::global::init_global_db; #[cfg(not(target_arch = "wasm32"))] use crate::database::init_and_migrate_sql_db; use crate::lp_healthcheck::peer_healthcheck_topic; @@ -394,6 +396,9 @@ pub async fn lp_init_continue(ctx: MmArc) -> MmInitResult<()> { ctx.init_global_and_wallet_db() .await .map_to_mm(MmInitError::ErrorSqliteInitializing)?; + init_global_db(&ctx) + .await + .map_to_mm(|e| MmInitError::ErrorSqliteInitializing(e.to_string()))?; } } diff --git a/mm2src/mm2_main/src/lp_ordermatch.rs b/mm2src/mm2_main/src/lp_ordermatch.rs index f874eac21b..c1e5d854cb 100644 --- a/mm2src/mm2_main/src/lp_ordermatch.rs +++ b/mm2src/mm2_main/src/lp_ordermatch.rs @@ -3244,6 +3244,10 @@ async fn start_maker_legacy_swap( ) { if let Err(e) = insert_new_swap_to_db( ctx.clone(), + ¶ms + .maker_coin + .address_from_pubkey(&(*params.my_persistent_pub).into()) + .unwrap(), params.maker_coin.ticker(), params.taker_coin.ticker(), *params.uuid, @@ -3496,6 +3500,10 @@ async fn start_taker_legacy_swap( if let Err(e) = insert_new_swap_to_db( ctx.clone(), + ¶ms + .maker_coin + .address_from_pubkey(&(*params.my_persistent_pub).into()) + .unwrap(), params.taker_coin.ticker(), params.maker_coin.ticker(), *params.uuid, diff --git a/mm2src/mm2_main/src/lp_swap.rs b/mm2src/mm2_main/src/lp_swap.rs index 29b8b6fdf2..d9b3cbbdea 100644 --- a/mm2src/mm2_main/src/lp_swap.rs +++ b/mm2src/mm2_main/src/lp_swap.rs @@ -970,6 +970,7 @@ pub fn my_swap_file_path(ctx: &MmArc, address: &str, uuid: &Uuid) -> PathBuf { pub async fn insert_new_swap_to_db( ctx: MmArc, + maker_address: &str, my_coin: &str, other_coin: &str, uuid: Uuid, @@ -977,16 +978,18 @@ pub async fn insert_new_swap_to_db( swap_type: u8, ) -> Result<(), String> { MySwapsStorage::new(ctx) - .save_new_swap(my_coin, other_coin, uuid, started_at, swap_type) + .save_new_swap(my_coin, other_coin, maker_address, uuid, started_at, swap_type) .await .map_err(|e| ERRL!("{}", e)) } #[cfg(not(target_arch = "wasm32"))] fn add_swap_to_db_index(ctx: &MmArc, swap: &SavedSwap) { - if let Some(conn) = ctx.sqlite_conn_opt() { - crate::database::stats_swaps::add_swap_to_index(&conn, swap) - } + #[cfg(not(feature = "new-db-arch"))] + let conn = ctx.sqlite_connection(); + #[cfg(feature = "new-db-arch")] + let conn = ctx.global_db(); + crate::database::stats_swaps::add_swap_to_index(&conn, swap) } #[cfg(not(target_arch = "wasm32"))] @@ -1504,8 +1507,13 @@ pub async fn import_swaps(ctx: MmArc, req: Json) -> Result>, St match swap.save_to_db(&ctx).await { Ok(_) => { if let Some(info) = swap.get_my_info() { + #[cfg(all(not(target_arch = "wasm32"), feature = "new-db-arch"))] + let maker_address = swap.maker_address(); + #[cfg(not(feature = "new-db-arch"))] + let maker_address = "no maker-address/address-dir in old DB arch"; if let Err(e) = insert_new_swap_to_db( ctx.clone(), + maker_address, &info.my_coin, &info.other_coin, *swap.uuid(), diff --git a/mm2src/mm2_main/src/lp_swap/maker_swap_v2.rs b/mm2src/mm2_main/src/lp_swap/maker_swap_v2.rs index 53dbc1d6e7..7fa11921ef 100644 --- a/mm2src/mm2_main/src/lp_swap/maker_swap_v2.rs +++ b/mm2src/mm2_main/src/lp_swap/maker_swap_v2.rs @@ -38,6 +38,7 @@ use uuid::Uuid; cfg_native!( use crate::database::my_swaps::{insert_new_swap_v2, SELECT_MY_SWAP_V2_BY_UUID}; + #[cfg(feature = "new-db-arch")] use crate::database::global; use common::async_blocking; use db_common::sqlite::rusqlite::{named_params, Error as SqlError, Result as SqlResult, Row}; use db_common::sqlite::rusqlite::types::Type as SqlType; @@ -225,8 +226,23 @@ impl StateMachineStorage for MakerSwapStorage { let ctx = self.ctx.clone(); let id_str = id.to_string(); + #[cfg(feature = "new-db-arch")] + let address_dir = global::get_maker_address_for_swap_uuid(&ctx, &id) + .await + .map_err(|e| SwapStateMachineError::StorageError(e.to_string()))? + .ok_or_else(|| SwapStateMachineError::StorageError(format!("No swap with UUID={} found.", id)))?; + #[cfg(not(feature = "new-db-arch"))] + let address_dir = String::from("address_dir doesn't have any effect in feature != new-db-arch"); + + let conn = ctx.address_db(&address_dir).map_err(|e| { + SwapStateMachineError::StorageError(format!( + "Failed to get address db for swap UUID={} and address_dir={}: {}", + id, address_dir, e + )) + })?; + async_blocking(move || { - Ok(ctx.sqlite_connection().query_row( + Ok(conn.query_row( SELECT_MY_SWAP_V2_BY_UUID, &[(":uuid", &id_str)], MakerSwapDbRepr::from_sql_row, diff --git a/mm2src/mm2_main/src/lp_swap/my_swaps_storage.rs b/mm2src/mm2_main/src/lp_swap/my_swaps_storage.rs index 150e8b9489..ab10d4ded5 100644 --- a/mm2src/mm2_main/src/lp_swap/my_swaps_storage.rs +++ b/mm2src/mm2_main/src/lp_swap/my_swaps_storage.rs @@ -35,6 +35,7 @@ pub trait MySwapsOps { &self, my_coin: &str, other_coin: &str, + address_dir: &str, uuid: Uuid, started_at: u64, swap_type: u8, @@ -58,6 +59,8 @@ impl MySwapsStorage { #[cfg(not(target_arch = "wasm32"))] mod native_impl { use super::*; + #[cfg(feature = "new-db-arch")] + use crate::database::global::insert_swap_in_global_db; use crate::database::my_swaps::{insert_new_swap, select_uuids_by_my_swaps_filter, SelectSwapsUuidsErr}; use db_common::sqlite::rusqlite::Error as SqlError; @@ -80,12 +83,20 @@ mod native_impl { &self, my_coin: &str, other_coin: &str, + address_dir: &str, uuid: Uuid, started_at: u64, swap_type: u8, ) -> MySwapsResult<()> { + #[cfg(feature = "new-db-arch")] + insert_swap_in_global_db(&self.ctx, &uuid, address_dir) + .await + .map_err(|e| MySwapsError::InternalError(e.to_string()))?; Ok(insert_new_swap( - &self.ctx, + &self + .ctx + .address_db(address_dir) + .map_err(|e| MySwapsError::InternalError(e.to_string()))?, my_coin, other_coin, &uuid.to_string(), @@ -172,6 +183,7 @@ mod wasm_impl { &self, my_coin: &str, other_coin: &str, + _address_dir: &str, uuid: Uuid, started_at: u64, swap_type: u8, @@ -389,7 +401,14 @@ mod wasm_tests { }); } my_swaps - .save_new_swap(my_coin, other_coin, uuid, started_at, swap_type) + .save_new_swap( + my_coin, + other_coin, + "address directory/specifier has no usage in wasm right now", + uuid, + started_at, + swap_type, + ) .await .expect("!MySwapsStorage::save_new_swap"); } diff --git a/mm2src/mm2_main/src/lp_swap/saved_swap.rs b/mm2src/mm2_main/src/lp_swap/saved_swap.rs index 93c6eabf29..87dba79551 100644 --- a/mm2src/mm2_main/src/lp_swap/saved_swap.rs +++ b/mm2src/mm2_main/src/lp_swap/saved_swap.rs @@ -198,6 +198,8 @@ pub trait SavedSwapIo { #[cfg(not(target_arch = "wasm32"))] mod native_impl { use super::*; + #[cfg(feature = "new-db-arch")] + use crate::database::global::get_maker_address_for_swap_uuid; use crate::lp_swap::maker_swap::{stats_maker_swap_dir, stats_maker_swap_file_path}; use crate::lp_swap::taker_swap::{stats_taker_swap_dir, stats_taker_swap_file_path}; use crate::lp_swap::{my_swap_file_path, my_swaps_dir}; @@ -225,12 +227,17 @@ mod native_impl { address_dir: Option<&str>, uuid: Uuid, ) -> SavedSwapResult> { - // TODO(new-db-arch): Set the correct address directory for the new db arch branch (via a query to the global DB). - #[cfg(feature = "new-db-arch")] - let address_dir = address_dir.unwrap_or("Fetch the address directory from the global DB given the UUID."); - #[cfg(not(feature = "new-db-arch"))] - let address_dir = address_dir.unwrap_or("no address directory for old DB architecture (has no effect)"); - let path = my_swap_file_path(ctx, address_dir, &uuid); + let path = match address_dir { + Some(addr) => my_swap_file_path(ctx, addr, &uuid), + #[cfg(feature = "new-db-arch")] + None => match get_maker_address_for_swap_uuid(ctx, &uuid).await { + Ok(Some(maker_address)) => my_swap_file_path(ctx, &maker_address, &uuid), + Ok(None) => return Ok(None), + Err(e) => return MmError::err(SavedSwapError::InternalError(e.to_string())), + }, + #[cfg(not(feature = "new-db-arch"))] + None => my_swap_file_path(ctx, "address directory has no effect in old DB arch anyway", &uuid), + }; Ok(read_json(&path).await.map_mm_err()?) } @@ -238,7 +245,7 @@ mod native_impl { async fn load_all_my_swaps_from_db(ctx: &MmArc) -> SavedSwapResult> { #[cfg(feature = "new-db-arch")] { - // This method is solely used for migrations. Which we should ditch or refactor with the new DB architecture. + // TODO: This method is solely used for migrations. Which we should ditch or refactor with the new DB architecture. // If we ditch the old migrations, this method should never be called (and should be deleted when we are // done with the incremental architecture change). todo!("Fix the dummy address directory in `my_swaps_dir` below or remove this method all together"); @@ -247,6 +254,16 @@ mod native_impl { Ok(read_dir_json(&path).await.map_mm_err()?) } + async fn save_to_db(&self, ctx: &MmArc) -> SavedSwapResult<()> { + #[cfg(feature = "new-db-arch")] + let address_dir = self.maker_address(); + #[cfg(not(feature = "new-db-arch"))] + let address_dir = "no address directory for old DB architecture (has no effect)"; + let path = my_swap_file_path(ctx, address_dir, self.uuid()); + write_json(self, &path, USE_TMP_FILE).await.map_mm_err()?; + Ok(()) + } + async fn load_from_maker_stats_db(ctx: &MmArc, uuid: Uuid) -> SavedSwapResult> { let path = stats_maker_swap_file_path(ctx, &uuid); Ok(read_json(&path).await.map_mm_err()?) @@ -267,16 +284,6 @@ mod native_impl { Ok(read_dir_json(&path).await.map_mm_err()?) } - async fn save_to_db(&self, ctx: &MmArc) -> SavedSwapResult<()> { - #[cfg(feature = "new-db-arch")] - let address_dir = self.maker_address(); - #[cfg(not(feature = "new-db-arch"))] - let address_dir = "no address directory for old DB architecture (has no effect)"; - let path = my_swap_file_path(ctx, address_dir, self.uuid()); - write_json(self, &path, USE_TMP_FILE).await.map_mm_err()?; - Ok(()) - } - /// Save the inner maker/taker swap to the corresponding stats db. async fn save_to_stats_db(&self, ctx: &MmArc) -> SavedSwapResult<()> { match self { diff --git a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs index 1356a6f644..cbb69947c1 100644 --- a/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs +++ b/mm2src/mm2_main/src/lp_swap/swap_v2_common.rs @@ -67,6 +67,7 @@ pub enum SwapStateMachineError { SerdeError(String), SwapLockAlreadyAcquired, SwapLock(SwapLockError), + InternalError(String), #[cfg(target_arch = "wasm32")] NoSwapWithUuid(Uuid), } diff --git a/mm2src/mm2_main/src/lp_swap/swap_v2_rpcs.rs b/mm2src/mm2_main/src/lp_swap/swap_v2_rpcs.rs index b6490338de..90b0e9d6fa 100644 --- a/mm2src/mm2_main/src/lp_swap/swap_v2_rpcs.rs +++ b/mm2src/mm2_main/src/lp_swap/swap_v2_rpcs.rs @@ -19,6 +19,7 @@ use uuid::Uuid; cfg_native!( use crate::database::my_swaps::SELECT_MY_SWAP_V2_FOR_RPC_BY_UUID; + #[cfg(feature = "new-db-arch")] use crate::database::global; use common::async_blocking; use db_common::sqlite::query_single_row; use db_common::sqlite::rusqlite::{Result as SqlResult, Row, Error as SqlError}; @@ -34,18 +35,29 @@ cfg_wasm32!( ); #[cfg(not(target_arch = "wasm32"))] -pub(super) async fn get_swap_type(ctx: &MmArc, uuid: &Uuid) -> MmResult, SqlError> { +pub(super) async fn get_swap_type(ctx: &MmArc, uuid: &Uuid) -> MmResult, String> { let ctx = ctx.clone(); - let uuid = uuid.to_string(); + let uuid_str = uuid.to_string(); + + #[cfg(feature = "new-db-arch")] + let address_dir = match global::get_maker_address_for_swap_uuid(&ctx, uuid).await? { + Some(addr) => addr, + None => return Ok(None), + }; + #[cfg(not(feature = "new-db-arch"))] + let address_dir = String::from("address_dir doesn't have any effect in feature != new-db-arch"); + + let conn = ctx.address_db(&address_dir)?; async_blocking(move || { const SELECT_SWAP_TYPE_BY_UUID: &str = "SELECT swap_type FROM my_swaps WHERE uuid = :uuid;"; let maybe_swap_type = query_single_row( - &ctx.sqlite_connection(), + &conn, SELECT_SWAP_TYPE_BY_UUID, - &[(":uuid", uuid.as_str())], + &[(":uuid", uuid_str.as_str())], |row| row.get(0), - )?; + ) + .map_err(|e| e.to_string())?; Ok(maybe_swap_type) }) .await @@ -151,7 +163,7 @@ impl MySwapForRpc { pub(super) async fn get_maker_swap_data_for_rpc( ctx: &MmArc, uuid: &Uuid, -) -> MmResult>, SqlError> { +) -> MmResult>, String> { get_swap_data_for_rpc_impl(ctx, uuid).await } @@ -159,7 +171,7 @@ pub(super) async fn get_maker_swap_data_for_rpc( pub(super) async fn get_taker_swap_data_for_rpc( ctx: &MmArc, uuid: &Uuid, -) -> MmResult>, SqlError> { +) -> MmResult>, String> { get_swap_data_for_rpc_impl(ctx, uuid).await } @@ -167,17 +179,28 @@ pub(super) async fn get_taker_swap_data_for_rpc( async fn get_swap_data_for_rpc_impl( ctx: &MmArc, uuid: &Uuid, -) -> MmResult>, SqlError> { +) -> MmResult>, String> { let ctx = ctx.clone(); - let uuid = uuid.to_string(); + let uuid_str = uuid.to_string(); + + #[cfg(feature = "new-db-arch")] + let address_dir = match global::get_maker_address_for_swap_uuid(&ctx, uuid).await? { + Some(addr) => addr, + None => return Ok(None), + }; + #[cfg(not(feature = "new-db-arch"))] + let address_dir = String::from("address_dir doesn't have any effect in feature != new-db-arch"); + + let conn = ctx.address_db(&address_dir)?; async_blocking(move || { let swap_data = query_single_row( - &ctx.sqlite_connection(), + &conn, SELECT_MY_SWAP_V2_FOR_RPC_BY_UUID, - &[(":uuid", uuid.as_str())], + &[(":uuid", uuid_str.as_str())], MySwapForRpc::from_row, - )?; + ) + .map_err(|e| e.to_string())?; Ok(swap_data) }) .await @@ -285,21 +308,21 @@ pub(crate) enum SwapRpcData { #[derive(Display)] enum GetSwapDataErr { UnsupportedSwapType(u8), - DbError(String), + InternalError(String), } impl From for GetSwapDataErr { - fn from(e: SavedSwapError) -> Self { GetSwapDataErr::DbError(e.to_string()) } + fn from(e: SavedSwapError) -> Self { GetSwapDataErr::InternalError(e.to_string()) } } #[cfg(not(target_arch = "wasm32"))] -impl From for GetSwapDataErr { - fn from(e: SqlError) -> Self { GetSwapDataErr::DbError(e.to_string()) } +impl From for GetSwapDataErr { + fn from(e: String) -> Self { GetSwapDataErr::InternalError(e) } } #[cfg(target_arch = "wasm32")] impl From for GetSwapDataErr { - fn from(e: SwapV2DbError) -> Self { GetSwapDataErr::DbError(e.to_string()) } + fn from(e: SwapV2DbError) -> Self { GetSwapDataErr::InternalError(e.to_string()) } } async fn get_swap_data_by_uuid_and_type( @@ -337,24 +360,24 @@ pub(crate) struct MySwapStatusRequest { pub(crate) enum MySwapStatusError { NoSwapWithUuid(Uuid), UnsupportedSwapType(u8), - DbError(String), + InternalError(String), } #[cfg(not(target_arch = "wasm32"))] -impl From for MySwapStatusError { - fn from(e: SqlError) -> Self { MySwapStatusError::DbError(e.to_string()) } +impl From for MySwapStatusError { + fn from(e: String) -> Self { MySwapStatusError::InternalError(e) } } #[cfg(target_arch = "wasm32")] impl From for MySwapStatusError { - fn from(e: SwapV2DbError) -> Self { MySwapStatusError::DbError(e.to_string()) } + fn from(e: SwapV2DbError) -> Self { MySwapStatusError::InternalError(e.to_string()) } } impl From for MySwapStatusError { fn from(e: GetSwapDataErr) -> Self { match e { GetSwapDataErr::UnsupportedSwapType(swap_type) => MySwapStatusError::UnsupportedSwapType(swap_type), - GetSwapDataErr::DbError(err) => MySwapStatusError::DbError(err), + GetSwapDataErr::InternalError(err) => MySwapStatusError::InternalError(err), } } } @@ -363,7 +386,7 @@ impl HttpStatusCode for MySwapStatusError { fn status_code(&self) -> StatusCode { match self { MySwapStatusError::NoSwapWithUuid(_) => StatusCode::BAD_REQUEST, - MySwapStatusError::DbError(_) | MySwapStatusError::UnsupportedSwapType(_) => { + MySwapStatusError::InternalError(_) | MySwapStatusError::UnsupportedSwapType(_) => { StatusCode::INTERNAL_SERVER_ERROR }, } diff --git a/mm2src/mm2_main/src/lp_swap/taker_swap_v2.rs b/mm2src/mm2_main/src/lp_swap/taker_swap_v2.rs index b3ee43a6a1..fe75888b84 100644 --- a/mm2src/mm2_main/src/lp_swap/taker_swap_v2.rs +++ b/mm2src/mm2_main/src/lp_swap/taker_swap_v2.rs @@ -38,6 +38,7 @@ use uuid::Uuid; cfg_native!( use crate::database::my_swaps::{insert_new_swap_v2, SELECT_MY_SWAP_V2_BY_UUID}; + #[cfg(feature = "new-db-arch")] use crate::database::global; use common::async_blocking; use db_common::sqlite::rusqlite::{named_params, Error as SqlError, Result as SqlResult, Row}; use db_common::sqlite::rusqlite::types::Type as SqlType; @@ -256,8 +257,23 @@ impl StateMachineStorage for TakerSwapStorage { let ctx = self.ctx.clone(); let id_str = id.to_string(); + #[cfg(feature = "new-db-arch")] + let address_dir = global::get_maker_address_for_swap_uuid(&ctx, &id) + .await + .map_err(|e| SwapStateMachineError::StorageError(e.to_string()))? + .ok_or_else(|| SwapStateMachineError::StorageError(format!("No swap with UUID={} found.", id)))?; + #[cfg(not(feature = "new-db-arch"))] + let address_dir = String::from("address_dir doesn't have any effect in feature != new-db-arch"); + + let conn = ctx.address_db(&address_dir).map_err(|e| { + SwapStateMachineError::StorageError(format!( + "Failed to get address db for swap UUID={} and address_dir={}: {}", + id, address_dir, e + )) + })?; + async_blocking(move || { - Ok(ctx.sqlite_connection().query_row( + Ok(conn.query_row( SELECT_MY_SWAP_V2_BY_UUID, &[(":uuid", &id_str)], TakerSwapDbRepr::from_sql_row,