diff --git a/crates/diesel_models/src/errors.rs b/crates/diesel_models/src/errors.rs index 0a8422131ae2..30e4273fdb57 100644 --- a/crates/diesel_models/src/errors.rs +++ b/crates/diesel_models/src/errors.rs @@ -10,7 +10,15 @@ pub enum DatabaseError { NoFieldsToUpdate, #[error("An error occurred when generating typed SQL query")] QueryGenerationFailed, + #[error("DB transaction failure")] + TransactionFailed(String), // InsertFailed, #[error("An unknown error occurred")] Others, } + +impl From for DatabaseError { + fn from(err: diesel::result::Error) -> Self { + Self::TransactionFailed(err.to_string()) + } +} diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index c0d6c576dd56..0472ffb41989 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -111,10 +111,6 @@ pub async fn create_merchant_account( .payment_response_hash_key .or(Some(generate_cryptographically_secure_random_string(64))); - db.insert_merchant_key_store(key_store.clone(), &master_key.to_vec().into()) - .await - .to_duplicate_response(errors::ApiErrorResponse::DuplicateMerchantAccount)?; - let parent_merchant_id = get_parent_merchant( db, req.sub_merchants_enabled, diff --git a/crates/router/src/db/merchant_account.rs b/crates/router/src/db/merchant_account.rs index e0bff7d9069c..5f533eabc9f6 100644 --- a/crates/router/src/db/merchant_account.rs +++ b/crates/router/src/db/merchant_account.rs @@ -1,3 +1,4 @@ +use async_bb8_diesel::AsyncConnection; use common_utils::ext_traits::AsyncExt; use error_stack::{IntoReport, ResultExt}; #[cfg(feature = "accounts_cache")] @@ -72,20 +73,36 @@ impl MerchantAccountInterface for Store { async fn insert_merchant( &self, merchant_account: domain::MerchantAccount, - merchant_key_store: &domain::MerchantKeyStore, + merchant_key_store: domain::MerchantKeyStore, ) -> CustomResult { let conn = connection::pg_connection_write(self).await?; - merchant_account - .construct_new() - .await - .change_context(errors::StorageError::EncryptionError)? - .insert(&conn) - .await - .map_err(Into::into) - .into_report()? - .convert(merchant_key_store.key.get_inner()) - .await - .change_context(errors::StorageError::DecryptionError) + + conn.transaction_async(|e| async move { + let key_store = merchant_key_store + .construct_new() + .await + .change_context(errors::StorageError::EncryptionError)? + .insert(&e) + .await + .map_err(Into::into) + .into_report()? + .convert(&self.get_master_key().to_vec().into()) + .await + .change_context(errors::StorageError::DecryptionError); + + merchant_account + .construct_new() + .await + .change_context(errors::StorageError::EncryptionError)? + .insert(&e) + .await + .map_err(Into::into) + .into_report()? + .convert(merchant_key_store.key.get_inner()) + .await + .change_context(errors::StorageError::DecryptionError) + }) + .await } async fn find_merchant_account_by_merchant_id( diff --git a/crates/storage_impl/src/errors.rs b/crates/storage_impl/src/errors.rs index bc68986cb8ea..c8abccdf4b62 100644 --- a/crates/storage_impl/src/errors.rs +++ b/crates/storage_impl/src/errors.rs @@ -98,6 +98,9 @@ impl Into for &StorageError { storage_errors::DatabaseError::QueryGenerationFailed => { DataStorageError::DatabaseError("Query generation failed".to_string()) } + storage_errors::DatabaseError::TransactionFailed(e) => { + DataStorageError::DatabaseError(e.to_string()) + } storage_errors::DatabaseError::Others => { DataStorageError::DatabaseError("Unknown database error".to_string()) } diff --git a/crates/storage_impl/src/lib.rs b/crates/storage_impl/src/lib.rs index dd8d71fc701e..406c6ee9ab8b 100644 --- a/crates/storage_impl/src/lib.rs +++ b/crates/storage_impl/src/lib.rs @@ -245,6 +245,9 @@ pub(crate) fn diesel_error_to_data_error( diesel_models::errors::DatabaseError::QueryGenerationFailed => { StorageError::DatabaseError("Query generation failed".to_string()) } + store::errors::DatabaseError::TransactionFailed(e) => { + StorageError::DatabaseError(e.to_string()) + } diesel_models::errors::DatabaseError::Others => { StorageError::DatabaseError("Others".to_string()) }