use std::time::Duration;
use tokio::time::timeout;
use crate::{
client::{secret::SecretManage, ClientError},
wallet::{operations::syncing::SyncOptions, task, Wallet, WalletError},
};
pub(crate) const DEFAULT_BACKGROUNDSYNCING_INTERVAL: Duration = Duration::from_secs(7);
#[derive(Clone, PartialEq, Debug)]
pub(crate) enum BackgroundSyncStatus {
Stopped,
Running,
Stopping,
}
impl<S: 'static + SecretManage> Wallet<S>
where
WalletError: From<S::Error>,
ClientError: From<S::Error>,
{
pub async fn start_background_syncing(
&self,
options: impl Into<Option<SyncOptions>> + Send,
interval: Option<Duration>,
) -> Result<(), WalletError> {
log::debug!("[start_background_syncing]");
let options = options.into();
let (tx_background_sync, mut rx_background_sync) = self.background_syncing_status.clone();
if *rx_background_sync.borrow() == BackgroundSyncStatus::Running {
tx_background_sync.send(BackgroundSyncStatus::Stopping).ok();
}
log::debug!("[background_syncing]: waiting for the old process to stop");
rx_background_sync
.wait_for(|status| *status != BackgroundSyncStatus::Stopping)
.await
.ok();
tx_background_sync.send(BackgroundSyncStatus::Running).ok();
let wallet = self.clone();
let interval_seconds = interval.unwrap_or(DEFAULT_BACKGROUNDSYNCING_INTERVAL);
task::spawn(async move {
loop {
log::debug!("[background_syncing]: syncing wallet");
if let Err(err) = wallet.sync(options).await {
log::debug!("[background_syncing] error: {}", err)
}
let res = timeout(interval_seconds, async {
rx_background_sync
.wait_for(|status| *status == BackgroundSyncStatus::Stopping)
.await
.is_ok()
})
.await;
if Ok(true) == res {
log::debug!("[background_syncing]: stopping");
break;
}
}
tx_background_sync.send(BackgroundSyncStatus::Stopped).ok();
log::debug!("[background_syncing]: stopped");
});
Ok(())
}
pub fn request_stop_background_syncing(&self) {
log::debug!("[request_stop_background_syncing]");
self.background_syncing_status
.0
.send(BackgroundSyncStatus::Stopping)
.ok();
}
pub async fn stop_background_syncing(&self) -> Result<(), WalletError> {
log::debug!("[stop_background_syncing]");
let mut rx_background_sync = self.background_syncing_status.1.clone();
if *rx_background_sync.borrow() == BackgroundSyncStatus::Stopped {
return Ok(());
}
self.request_stop_background_syncing();
rx_background_sync
.wait_for(|status| *status == BackgroundSyncStatus::Stopped)
.await
.ok();
Ok(())
}
}