Skip to content

Commit 7d931bf

Browse files
authored
Merge pull request #881 from tnull/2026-04-fix-615
Read the RGS sync timestamp from the network graph
2 parents 21eea8c + d1065db commit 7d931bf

7 files changed

Lines changed: 137 additions & 109 deletions

File tree

src/builder.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ use crate::io::sqlite_store::SqliteStore;
6161
use crate::io::utils::{
6262
read_event_queue, read_external_pathfinding_scores_from_cache, read_network_graph,
6363
read_node_metrics, read_output_sweeper, read_payments, read_peer_info, read_pending_payments,
64-
read_scorer, write_node_metrics,
64+
read_scorer,
6565
};
6666
use crate::io::vss_store::VssStoreBuilder;
6767
use crate::io::{
@@ -1843,21 +1843,11 @@ fn build_with_store_internal(
18431843
Arc::clone(&logger),
18441844
));
18451845

1846-
// Reset the RGS sync timestamp in case we somehow switch gossip sources
1847-
{
1848-
let mut locked_node_metrics = node_metrics.write().expect("lock");
1849-
locked_node_metrics.latest_rgs_snapshot_timestamp = None;
1850-
write_node_metrics(&*locked_node_metrics, &*kv_store, Arc::clone(&logger))
1851-
.map_err(|e| {
1852-
log_error!(logger, "Failed writing to store: {}", e);
1853-
BuildError::WriteFailed
1854-
})?;
1855-
}
18561846
p2p_source
18571847
},
18581848
GossipSourceConfig::RapidGossipSync(rgs_server) => {
18591849
let latest_sync_timestamp =
1860-
node_metrics.read().expect("lock").latest_rgs_snapshot_timestamp.unwrap_or(0);
1850+
network_graph.get_last_rapid_gossip_sync_timestamp().unwrap_or(0);
18611851
Arc::new(GossipSource::new_rgs(
18621852
rgs_server.clone(),
18631853
latest_sync_timestamp,

src/chain/bitcoind.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use crate::fee_estimator::{
3939
apply_post_estimation_adjustments, get_all_conf_targets, get_num_block_defaults_for_target,
4040
ConfirmationTarget, OnchainFeeEstimator,
4141
};
42-
use crate::io::utils::write_node_metrics;
42+
use crate::io::utils::update_and_persist_node_metrics;
4343
use crate::logger::{log_bytes, log_debug, log_error, log_info, log_trace, LdkLogger, Logger};
4444
use crate::types::{ChainMonitor, ChannelManager, DynStore, Sweeper, Wallet};
4545
use crate::{Error, NodeMetrics};
@@ -203,15 +203,18 @@ impl BitcoindChainSource {
203203
*self.latest_chain_tip.write().expect("lock") = Some(chain_tip);
204204
let unix_time_secs_opt =
205205
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
206-
let mut locked_node_metrics = self.node_metrics.write().expect("lock");
207-
locked_node_metrics.latest_lightning_wallet_sync_timestamp =
208-
unix_time_secs_opt;
209-
locked_node_metrics.latest_onchain_wallet_sync_timestamp =
210-
unix_time_secs_opt;
211-
write_node_metrics(&*locked_node_metrics, &*self.kv_store, &*self.logger)
212-
.unwrap_or_else(|e| {
213-
log_error!(self.logger, "Failed to persist node metrics: {}", e);
214-
});
206+
update_and_persist_node_metrics(
207+
&self.node_metrics,
208+
&*self.kv_store,
209+
&*self.logger,
210+
|m| {
211+
m.latest_lightning_wallet_sync_timestamp = unix_time_secs_opt;
212+
m.latest_onchain_wallet_sync_timestamp = unix_time_secs_opt;
213+
},
214+
)
215+
.unwrap_or_else(|e| {
216+
log_error!(self.logger, "Failed to persist node metrics: {}", e);
217+
});
215218
}
216219
break;
217220
},
@@ -454,11 +457,10 @@ impl BitcoindChainSource {
454457

455458
let unix_time_secs_opt =
456459
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
457-
let mut locked_node_metrics = self.node_metrics.write().expect("lock");
458-
locked_node_metrics.latest_lightning_wallet_sync_timestamp = unix_time_secs_opt;
459-
locked_node_metrics.latest_onchain_wallet_sync_timestamp = unix_time_secs_opt;
460-
461-
write_node_metrics(&*locked_node_metrics, &*self.kv_store, &*self.logger)?;
460+
update_and_persist_node_metrics(&self.node_metrics, &*self.kv_store, &*self.logger, |m| {
461+
m.latest_lightning_wallet_sync_timestamp = unix_time_secs_opt;
462+
m.latest_onchain_wallet_sync_timestamp = unix_time_secs_opt;
463+
})?;
462464

463465
Ok(())
464466
}
@@ -568,11 +570,9 @@ impl BitcoindChainSource {
568570

569571
let unix_time_secs_opt =
570572
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
571-
{
572-
let mut locked_node_metrics = self.node_metrics.write().expect("lock");
573-
locked_node_metrics.latest_fee_rate_cache_update_timestamp = unix_time_secs_opt;
574-
write_node_metrics(&*locked_node_metrics, &*self.kv_store, &*self.logger)?;
575-
}
573+
update_and_persist_node_metrics(&self.node_metrics, &*self.kv_store, &*self.logger, |m| {
574+
m.latest_fee_rate_cache_update_timestamp = unix_time_secs_opt
575+
})?;
576576

577577
Ok(())
578578
}

src/chain/electrum.rs

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::fee_estimator::{
3030
apply_post_estimation_adjustments, get_all_conf_targets, get_num_block_defaults_for_target,
3131
ConfirmationTarget, OnchainFeeEstimator,
3232
};
33-
use crate::io::utils::write_node_metrics;
33+
use crate::io::utils::update_and_persist_node_metrics;
3434
use crate::logger::{log_bytes, log_debug, log_error, log_trace, LdkLogger, Logger};
3535
use crate::runtime::Runtime;
3636
use crate::types::{ChainMonitor, ChannelManager, DynStore, Sweeper, Wallet};
@@ -141,16 +141,12 @@ impl ElectrumChainSource {
141141
);
142142
let unix_time_secs_opt =
143143
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
144-
{
145-
let mut locked_node_metrics = self.node_metrics.write().expect("lock");
146-
locked_node_metrics.latest_onchain_wallet_sync_timestamp =
147-
unix_time_secs_opt;
148-
write_node_metrics(
149-
&*locked_node_metrics,
150-
&*self.kv_store,
151-
&*self.logger,
152-
)?;
153-
}
144+
update_and_persist_node_metrics(
145+
&self.node_metrics,
146+
&*self.kv_store,
147+
&*self.logger,
148+
|m| m.latest_onchain_wallet_sync_timestamp = unix_time_secs_opt,
149+
)?;
154150
Ok(())
155151
},
156152
Err(e) => Err(e),
@@ -238,11 +234,12 @@ impl ElectrumChainSource {
238234
if let Ok(_) = res {
239235
let unix_time_secs_opt =
240236
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
241-
{
242-
let mut locked_node_metrics = self.node_metrics.write().expect("lock");
243-
locked_node_metrics.latest_lightning_wallet_sync_timestamp = unix_time_secs_opt;
244-
write_node_metrics(&*locked_node_metrics, &*self.kv_store, &*self.logger)?;
245-
}
237+
update_and_persist_node_metrics(
238+
&self.node_metrics,
239+
&*self.kv_store,
240+
&*self.logger,
241+
|m| m.latest_lightning_wallet_sync_timestamp = unix_time_secs_opt,
242+
)?;
246243
}
247244

248245
res
@@ -271,11 +268,9 @@ impl ElectrumChainSource {
271268

272269
let unix_time_secs_opt =
273270
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
274-
{
275-
let mut locked_node_metrics = self.node_metrics.write().expect("lock");
276-
locked_node_metrics.latest_fee_rate_cache_update_timestamp = unix_time_secs_opt;
277-
write_node_metrics(&*locked_node_metrics, &*self.kv_store, &*self.logger)?;
278-
}
271+
update_and_persist_node_metrics(&self.node_metrics, &*self.kv_store, &*self.logger, |m| {
272+
m.latest_fee_rate_cache_update_timestamp = unix_time_secs_opt
273+
})?;
279274

280275
Ok(())
281276
}

src/chain/esplora.rs

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::fee_estimator::{
2222
apply_post_estimation_adjustments, get_all_conf_targets, get_num_block_defaults_for_target,
2323
OnchainFeeEstimator,
2424
};
25-
use crate::io::utils::write_node_metrics;
25+
use crate::io::utils::update_and_persist_node_metrics;
2626
use crate::logger::{log_bytes, log_debug, log_error, log_trace, LdkLogger, Logger};
2727
use crate::types::{ChainMonitor, ChannelManager, DynStore, Sweeper, Wallet};
2828
use crate::{Error, NodeMetrics};
@@ -122,16 +122,13 @@ impl EsploraChainSource {
122122
.duration_since(UNIX_EPOCH)
123123
.ok()
124124
.map(|d| d.as_secs());
125-
{
126-
let mut locked_node_metrics = self.node_metrics.write().expect("lock");
127-
locked_node_metrics.latest_onchain_wallet_sync_timestamp = unix_time_secs_opt;
128-
write_node_metrics(
129-
&*locked_node_metrics,
130-
&*self.kv_store,
131-
&*self.logger
132-
)?;
133-
}
134-
Ok(())
125+
update_and_persist_node_metrics(
126+
&self.node_metrics,
127+
&*self.kv_store,
128+
&*self.logger,
129+
|m| m.latest_onchain_wallet_sync_timestamp = unix_time_secs_opt,
130+
)?;
131+
Ok(())
135132
},
136133
Err(e) => Err(e),
137134
},
@@ -263,12 +260,12 @@ impl EsploraChainSource {
263260

264261
let unix_time_secs_opt =
265262
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
266-
{
267-
let mut locked_node_metrics = self.node_metrics.write().expect("lock");
268-
locked_node_metrics.latest_lightning_wallet_sync_timestamp =
269-
unix_time_secs_opt;
270-
write_node_metrics(&*locked_node_metrics, &*self.kv_store, &*self.logger)?;
271-
}
263+
update_and_persist_node_metrics(
264+
&self.node_metrics,
265+
&*self.kv_store,
266+
&*self.logger,
267+
|m| m.latest_lightning_wallet_sync_timestamp = unix_time_secs_opt,
268+
)?;
272269
Ok(())
273270
},
274271
Err(e) => {
@@ -348,11 +345,9 @@ impl EsploraChainSource {
348345
);
349346
let unix_time_secs_opt =
350347
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
351-
{
352-
let mut locked_node_metrics = self.node_metrics.write().expect("lock");
353-
locked_node_metrics.latest_fee_rate_cache_update_timestamp = unix_time_secs_opt;
354-
write_node_metrics(&*locked_node_metrics, &*self.kv_store, &*self.logger)?;
355-
}
348+
update_and_persist_node_metrics(&self.node_metrics, &*self.kv_store, &*self.logger, |m| {
349+
m.latest_fee_rate_cache_update_timestamp = unix_time_secs_opt
350+
})?;
356351

357352
Ok(())
358353
}

src/io/utils.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::ops::Deref;
1111
#[cfg(unix)]
1212
use std::os::unix::fs::OpenOptionsExt;
1313
use std::path::Path;
14-
use std::sync::Arc;
14+
use std::sync::{Arc, RwLock};
1515

1616
use bdk_chain::indexer::keychain_txout::ChangeSet as BdkIndexerChangeSet;
1717
use bdk_chain::local_chain::ChangeSet as BdkLocalChainChangeSet;
@@ -346,13 +346,20 @@ where
346346
})
347347
}
348348

349-
pub(crate) fn write_node_metrics<L: Deref>(
350-
node_metrics: &NodeMetrics, kv_store: &DynStore, logger: L,
349+
/// Take a write lock on `node_metrics`, apply `update`, and persist the result to `kv_store`.
350+
///
351+
/// The write lock is held across the KV-store write, preserving the invariant that readers only
352+
/// observe the mutation once it has been durably persisted (or the persist has failed).
353+
pub(crate) fn update_and_persist_node_metrics<L: Deref>(
354+
node_metrics: &RwLock<NodeMetrics>, kv_store: &DynStore, logger: L,
355+
update: impl FnOnce(&mut NodeMetrics),
351356
) -> Result<(), Error>
352357
where
353358
L::Target: LdkLogger,
354359
{
355-
let data = node_metrics.encode();
360+
let mut locked_node_metrics = node_metrics.write().expect("lock");
361+
update(&mut *locked_node_metrics);
362+
let data = locked_node_metrics.encode();
356363
KVStoreSync::write(
357364
&*kv_store,
358365
NODE_METRICS_PRIMARY_NAMESPACE,

0 commit comments

Comments
 (0)