use anyhow::Context;
use lexe_node_client::client::NodeClient;
use tracing::{info, warn};
use super::{
ffs::{DiskFs, fsext},
payments_db::{self, PaymentsDb},
};
use crate::{config::WalletUserDbConfig, types::command::PaymentSyncSummary};
pub struct WalletDb<F> {
#[allow(dead_code)] user_db_config: WalletUserDbConfig,
payments_db: PaymentsDb<F>,
payment_sync_lock: tokio::sync::Mutex<()>,
}
impl WalletDb<DiskFs> {
pub fn fresh(user_db_config: WalletUserDbConfig) -> anyhow::Result<Self> {
let payments_ffs =
DiskFs::create_clean_dir_all(user_db_config.payments_db_dir())
.context("Could not create payments ffs")?;
for old_dir in user_db_config.old_payment_db_dirs() {
match fsext::remove_dir_all_idempotent(&old_dir) {
Ok(true) => info!("Deleted old payments_db dir: {old_dir:?}"),
Ok(false) => (),
Err(e) => warn!(?old_dir, "Couldn't delete old dir: {e:#}"),
}
}
Ok(Self {
user_db_config,
payments_db: PaymentsDb::empty(payments_ffs),
payment_sync_lock: tokio::sync::Mutex::new(()),
})
}
pub fn load(
user_db_config: WalletUserDbConfig,
) -> anyhow::Result<Option<Self>> {
if !user_db_config.user_db_dir().exists() {
return Ok(None);
}
let payments_ffs =
DiskFs::create_dir_all(user_db_config.payments_db_dir())
.context("Could not create payments ffs")?;
let payments_db = PaymentsDb::read(payments_ffs)
.context("Failed to load payments db")?;
let num_payments = payments_db.num_payments();
if num_payments == 0 {
for old_dir in user_db_config.old_payment_db_dirs() {
match fsext::remove_dir_all_idempotent(&old_dir) {
Ok(true) =>
info!("Deleted old payments_db dir: {old_dir:?}"),
Ok(false) => (),
Err(e) => warn!(?old_dir, "Couldn't delete old dir: {e:#}"),
}
}
}
let old_provision_db_dir = user_db_config.old_provision_db_dir();
match fsext::remove_dir_all_idempotent(&old_provision_db_dir) {
Ok(true) =>
info!("Deleted old provision_db dir: {old_provision_db_dir:?}"),
Ok(false) => (),
Err(e) =>
warn!(?old_provision_db_dir, "Couldn't delete old dir: {e:#}"),
}
let num_pending = payments_db.num_pending();
let latest_updated_index = payments_db.latest_updated_index();
info!(
%num_payments, %num_pending, ?latest_updated_index,
"Loaded WalletDb."
);
Ok(Some(Self {
user_db_config,
payments_db,
payment_sync_lock: tokio::sync::Mutex::new(()),
}))
}
pub fn load_or_fresh(
user_db_config: WalletUserDbConfig,
) -> anyhow::Result<Self> {
let maybe_db = Self::load(user_db_config.clone())
.context("Failed to load wallet db")?;
let db = match maybe_db {
Some(d) => d,
None => Self::fresh(user_db_config)
.context("Failed to create fresh wallet db")?,
};
Ok(db)
}
#[allow(dead_code)] pub fn user_db_config(&self) -> &WalletUserDbConfig {
&self.user_db_config
}
pub fn payments_db(&self) -> &PaymentsDb<DiskFs> {
&self.payments_db
}
pub async fn sync_payments(
&self,
node_client: &NodeClient,
batch_size: u16,
) -> anyhow::Result<PaymentSyncSummary> {
let _lock = self.payment_sync_lock.lock().await;
payments_db::sync_payments(&self.payments_db, node_client, batch_size)
.await
}
}