lexe/unstable/
wallet_db.rs1use anyhow::Context;
4use lexe_node_client::client::NodeClient;
5use tracing::{debug, warn};
6
7use super::{
8 ffs::{DiskFs, fsext},
9 payments_db::{self, PaymentsDb},
10};
11use crate::{config::WalletUserDbConfig, types::command::PaymentSyncSummary};
12
13pub struct WalletDb<F> {
17 #[allow(dead_code)] user_db_config: WalletUserDbConfig,
19
20 payments_db: PaymentsDb<F>,
21 payment_sync_lock: tokio::sync::Mutex<()>,
22}
23
24impl WalletDb<DiskFs> {
33 pub fn fresh(user_db_config: WalletUserDbConfig) -> anyhow::Result<Self> {
35 let payments_ffs =
36 DiskFs::create_clean_dir_all(user_db_config.payments_db_dir())
37 .context("Could not create payments ffs")?;
38
39 for old_dir in user_db_config.old_payment_db_dirs() {
41 match fsext::remove_dir_all_idempotent(&old_dir) {
42 Ok(true) => debug!("Deleted old payments_db dir: {old_dir:?}"),
43 Ok(false) => (),
44 Err(e) => warn!(?old_dir, "Couldn't delete old dir: {e:#}"),
45 }
46 }
47
48 Ok(Self {
49 user_db_config,
50 payments_db: PaymentsDb::empty(payments_ffs),
51 payment_sync_lock: tokio::sync::Mutex::new(()),
52 })
53 }
54
55 pub fn load(
57 user_db_config: WalletUserDbConfig,
58 ) -> anyhow::Result<Option<Self>> {
59 if !user_db_config.user_db_dir().exists() {
60 return Ok(None);
61 }
62
63 let payments_ffs =
64 DiskFs::create_dir_all(user_db_config.payments_db_dir())
65 .context("Could not create payments ffs")?;
66
67 let payments_db = PaymentsDb::read(payments_ffs)
68 .context("Failed to load payments db")?;
69
70 let num_payments = payments_db.num_payments();
73 if num_payments == 0 {
74 for old_dir in user_db_config.old_payment_db_dirs() {
75 match fsext::remove_dir_all_idempotent(&old_dir) {
76 Ok(true) =>
77 debug!("Deleted old payments_db dir: {old_dir:?}"),
78 Ok(false) => (),
79 Err(e) => warn!(?old_dir, "Couldn't delete old dir: {e:#}"),
80 }
81 }
82 }
83
84 let old_provision_db_dir = user_db_config.old_provision_db_dir();
87 match fsext::remove_dir_all_idempotent(&old_provision_db_dir) {
88 Ok(true) =>
89 debug!("Deleted old provision_db dir: {old_provision_db_dir:?}"),
90 Ok(false) => (),
91 Err(e) =>
92 warn!(?old_provision_db_dir, "Couldn't delete old dir: {e:#}"),
93 }
94
95 let num_pending = payments_db.num_pending();
96 let latest_updated_index = payments_db.latest_updated_index();
97 let last_synced_at = payments_db.last_synced_at();
98 debug!(
99 %num_payments, %num_pending, ?latest_updated_index, ?last_synced_at,
100 "Loaded WalletDb."
101 );
102
103 Ok(Some(Self {
104 user_db_config,
105 payments_db,
106 payment_sync_lock: tokio::sync::Mutex::new(()),
107 }))
108 }
109
110 pub fn load_or_fresh(
112 user_db_config: WalletUserDbConfig,
113 ) -> anyhow::Result<Self> {
114 let maybe_db = Self::load(user_db_config.clone())
115 .context("Failed to load wallet db")?;
116
117 let db = match maybe_db {
118 Some(d) => d,
119 None => Self::fresh(user_db_config)
120 .context("Failed to create fresh wallet db")?,
121 };
122
123 Ok(db)
124 }
125
126 #[allow(dead_code)] pub fn user_db_config(&self) -> &WalletUserDbConfig {
129 &self.user_db_config
130 }
131
132 pub fn payments_db(&self) -> &PaymentsDb<DiskFs> {
134 &self.payments_db
135 }
136
137 pub async fn sync_payments(
142 &self,
143 node_client: &NodeClient,
144 batch_size: u16,
145 ) -> anyhow::Result<PaymentSyncSummary> {
146 let _lock = self.payment_sync_lock.lock().await;
147 payments_db::sync_payments(&self.payments_db, node_client, batch_size)
148 .await
149 }
150}