Skip to content

Commit 7331a62

Browse files
committed
feat: in-memory cache for bridge monitoring
Implement in-memory caching system for bridge monitoring data: - Add BridgeStatusCache with confirmation tracking - Optimize monitoring task with batch updates and purging - Reduce RPC calls by caching active entries - Add selective status filtering and cache management
1 parent 1666a88 commit 7331a62

5 files changed

Lines changed: 584 additions & 109 deletions

File tree

backend/src/bridge/cache.rs

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
use bitcoin::Txid;
2+
use std::collections::HashMap;
3+
use std::time::{SystemTime, UNIX_EPOCH};
4+
use strata_primitives::buf::Buf32;
5+
6+
use super::types::{
7+
DepositInfo, DepositStatus, OperatorStatus, ReimbursementInfo, ReimbursementStatus,
8+
WithdrawalInfo, WithdrawalStatus,
9+
};
10+
11+
/// Cache entry with timestamp and confirmation tracking
12+
#[derive(Debug, Clone)]
13+
pub(crate) struct CacheEntry<T> {
14+
pub(crate) data: T,
15+
pub(crate) confirmations: u64,
16+
pub(crate) last_updated: u64,
17+
}
18+
19+
impl<T> CacheEntry<T> {
20+
pub(crate) fn new(data: T, confirmations: u64) -> Self {
21+
let now = SystemTime::now()
22+
.duration_since(UNIX_EPOCH)
23+
.unwrap()
24+
.as_secs();
25+
Self {
26+
data,
27+
confirmations,
28+
last_updated: now,
29+
}
30+
}
31+
32+
pub(crate) fn update(&mut self, data: T, confirmations: u64) {
33+
self.data = data;
34+
self.confirmations = confirmations;
35+
self.last_updated = SystemTime::now()
36+
.duration_since(UNIX_EPOCH)
37+
.unwrap()
38+
.as_secs();
39+
}
40+
}
41+
42+
/// In-memory cache for bridge monitoring data
43+
#[derive(Debug, Default, Clone)]
44+
pub(crate) struct BridgeStatusCache {
45+
deposits: HashMap<Txid, CacheEntry<DepositInfo>>,
46+
withdrawals: HashMap<Buf32, CacheEntry<WithdrawalInfo>>,
47+
reimbursements: HashMap<Txid, CacheEntry<ReimbursementInfo>>,
48+
operators: Vec<OperatorStatus>,
49+
}
50+
51+
impl BridgeStatusCache {
52+
pub(crate) fn new() -> Self {
53+
Self {
54+
deposits: HashMap::new(),
55+
withdrawals: HashMap::new(),
56+
reimbursements: HashMap::new(),
57+
operators: Vec::new(),
58+
}
59+
}
60+
61+
/// Update deposit cache entry
62+
pub(crate) fn update_deposit(&mut self, txid: Txid, info: DepositInfo, confirmations: u64) {
63+
if let Some(entry) = self.deposits.get_mut(&txid) {
64+
entry.update(info, confirmations);
65+
} else {
66+
self.deposits
67+
.insert(txid, CacheEntry::new(info, confirmations));
68+
}
69+
}
70+
71+
/// Update withdrawal cache entry
72+
pub(crate) fn update_withdrawal(
73+
&mut self,
74+
request_id: Buf32,
75+
info: WithdrawalInfo,
76+
confirmations: u64,
77+
) {
78+
if let Some(entry) = self.withdrawals.get_mut(&request_id) {
79+
entry.update(info, confirmations);
80+
} else {
81+
self.withdrawals
82+
.insert(request_id, CacheEntry::new(info, confirmations));
83+
}
84+
}
85+
86+
/// Update reimbursement cache entry
87+
pub(crate) fn update_reimbursement(
88+
&mut self,
89+
txid: Txid,
90+
info: ReimbursementInfo,
91+
confirmations: u64,
92+
) {
93+
if let Some(entry) = self.reimbursements.get_mut(&txid) {
94+
entry.update(info, confirmations);
95+
} else {
96+
self.reimbursements
97+
.insert(txid, CacheEntry::new(info, confirmations));
98+
}
99+
}
100+
101+
/// Update operators
102+
pub(crate) fn update_operators(&mut self, operators: Vec<OperatorStatus>) {
103+
self.operators = operators;
104+
}
105+
106+
/// Get all operators
107+
pub(crate) fn get_operators(&self) -> Vec<OperatorStatus> {
108+
self.operators.clone()
109+
}
110+
111+
/// Batch update deposits
112+
pub(crate) fn apply_deposit_updates(&mut self, updates: Vec<(Txid, DepositInfo, u64)>) {
113+
for (txid, info, confirmations) in updates {
114+
self.update_deposit(txid, info, confirmations);
115+
}
116+
}
117+
118+
/// Batch update withdrawals
119+
pub(crate) fn apply_withdrawal_updates(&mut self, updates: Vec<(Buf32, WithdrawalInfo, u64)>) {
120+
for (request_id, info, confirmations) in updates {
121+
self.update_withdrawal(request_id, info, confirmations);
122+
}
123+
}
124+
125+
/// Batch update reimbursements
126+
pub(crate) fn apply_reimbursement_updates(
127+
&mut self,
128+
updates: Vec<(Txid, ReimbursementInfo, u64)>,
129+
) {
130+
for (txid, info, confirmations) in updates {
131+
self.update_reimbursement(txid, info, confirmations);
132+
}
133+
}
134+
135+
/// Filter deposits based on status condition
136+
pub(crate) fn filter_deposits<F>(&self, filter: F) -> Vec<(Txid, DepositInfo)>
137+
where
138+
F: Fn(&DepositStatus) -> bool,
139+
{
140+
self.deposits
141+
.iter()
142+
.filter(|(_, entry)| filter(&entry.data.status))
143+
.map(|(txid, entry)| (*txid, entry.data.clone()))
144+
.collect()
145+
}
146+
147+
/// Filter withdrawals based on status condition
148+
pub(crate) fn filter_withdrawals<F>(&self, filter: F) -> Vec<(Buf32, WithdrawalInfo)>
149+
where
150+
F: Fn(&WithdrawalStatus) -> bool,
151+
{
152+
self.withdrawals
153+
.iter()
154+
.filter(|(_, entry)| filter(&entry.data.status))
155+
.map(|(request_id, entry)| (*request_id, entry.data.clone()))
156+
.collect()
157+
}
158+
159+
/// Filter reimbursements based on status condition
160+
pub(crate) fn filter_reimbursements<F>(&self, filter: F) -> Vec<(Txid, ReimbursementInfo)>
161+
where
162+
F: Fn(&ReimbursementStatus) -> bool,
163+
{
164+
self.reimbursements
165+
.iter()
166+
.filter(|(_, entry)| filter(&entry.data.status))
167+
.map(|(txid, entry)| (*txid, entry.data.clone()))
168+
.collect()
169+
}
170+
171+
/// Purge specific deposit entries
172+
pub(crate) fn purge_deposits(&mut self, deposits_to_purge: Vec<Txid>) {
173+
for txid in deposits_to_purge {
174+
self.deposits.remove(&txid);
175+
}
176+
}
177+
178+
/// Purge specific withdrawal entries
179+
pub(crate) fn purge_withdrawals(&mut self, withdrawals_to_purge: Vec<Buf32>) {
180+
for request_id in withdrawals_to_purge {
181+
self.withdrawals.remove(&request_id);
182+
}
183+
}
184+
185+
/// Purge specific reimbursement entries
186+
pub(crate) fn purge_reimbursements(&mut self, reimbursements_to_purge: Vec<Txid>) {
187+
for txid in reimbursements_to_purge {
188+
self.reimbursements.remove(&txid);
189+
}
190+
}
191+
}

backend/src/bridge/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
pub(crate) mod cache;
12
pub(crate) mod status;
23
pub(crate) mod types;

0 commit comments

Comments
 (0)