diff --git a/mutiny-core/src/keymanager.rs b/mutiny-core/src/keymanager.rs index 85364cc26..b69b8f3e6 100644 --- a/mutiny-core/src/keymanager.rs +++ b/mutiny-core/src/keymanager.rs @@ -250,6 +250,7 @@ mod tests { use bitcoin::Network; use esplora_client::Builder; use std::str::FromStr; + use std::sync::atomic::AtomicBool; use std::sync::Arc; #[test] @@ -270,6 +271,7 @@ mod tests { esplora.clone(), logger.clone(), )); + let stop = Arc::new(AtomicBool::new(false)); let wallet = Arc::new( OnChainWallet::new( @@ -278,6 +280,7 @@ mod tests { Network::Testnet, esplora, fees, + stop, logger.clone(), ) .unwrap(), diff --git a/mutiny-core/src/nodemanager.rs b/mutiny-core/src/nodemanager.rs index bd61994f4..b314e587f 100644 --- a/mutiny-core/src/nodemanager.rs +++ b/mutiny-core/src/nodemanager.rs @@ -495,6 +495,7 @@ impl NodeManager { network, esplora.clone(), fee_estimator.clone(), + stop.clone(), logger.clone(), )?); diff --git a/mutiny-core/src/onchain.rs b/mutiny-core/src/onchain.rs index d936d7096..9824658ef 100644 --- a/mutiny-core/src/onchain.rs +++ b/mutiny-core/src/onchain.rs @@ -1,6 +1,7 @@ use anyhow::anyhow; use std::collections::HashSet; use std::str::FromStr; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, RwLock}; use bdk::chain::{BlockId, ConfirmationTime}; @@ -22,6 +23,7 @@ use crate::fees::MutinyFeeEstimator; use crate::labels::*; use crate::logging::MutinyLogger; use crate::storage::{MutinyStorage, OnChainStorage}; +use crate::utils::sleep; #[derive(Clone)] pub struct OnChainWallet { @@ -30,6 +32,7 @@ pub struct OnChainWallet { pub network: Network, pub blockchain: Arc, pub fees: Arc>, + pub(crate) stop: Arc, logger: Arc, } @@ -40,6 +43,7 @@ impl OnChainWallet { network: Network, esplora: Arc, fees: Arc>, + stop: Arc, logger: Arc, ) -> Result, MutinyError> { let seed = mnemonic.to_seed(""); @@ -61,6 +65,7 @@ impl OnChainWallet { network, blockchain: esplora, fees, + stop, logger, }) } @@ -115,23 +120,37 @@ impl OnChainWallet { .await?; // get new wallet lock for writing and apply the update - match self.wallet.try_write() { - Ok(mut wallet) => match wallet.apply_update(update) { - Ok(_) => wallet.commit()?, + for _ in 0..10 { + match self.wallet.try_write() { + Ok(mut wallet) => match wallet.apply_update(update) { + Ok(_) => { + wallet.commit()?; + return Ok(()); + } + Err(e) => { + // failed to apply wallet update + log_error!(self.logger, "Could not apply wallet update: {e}"); + return Err(MutinyError::Other(anyhow!("Could not apply update: {e}"))); + } + }, Err(e) => { - // failed to apply wallet update - log_error!(self.logger, "Could not apply wallet update: {e}"); - return Err(MutinyError::Other(anyhow!("Could not apply update: {e}"))); + // if we can't get the lock, we just return and try again later + log_error!( + self.logger, + "Could not get wallet lock: {e}, retrying in 250ms" + ); + + if self.stop.load(Ordering::Relaxed) { + return Err(MutinyError::NotRunning); + }; + + sleep(250).await; } - }, - Err(e) => { - // if we can't get the lock, we just return and try again later - log_error!(self.logger, "Could not get wallet lock: {e}"); - return Ok(()); } } - Ok(()) + log_error!(self.logger, "Could not get wallet lock after 10 retries"); + Err(MutinyError::WalletOperationFailed) } pub(crate) async fn insert_tx( @@ -499,8 +518,9 @@ mod tests { esplora.clone(), logger.clone(), )); + let stop = Arc::new(AtomicBool::new(false)); - OnChainWallet::new(&mnemonic, db, Network::Testnet, esplora, fees, logger).unwrap() + OnChainWallet::new(&mnemonic, db, Network::Testnet, esplora, fees, stop, logger).unwrap() } #[test]