Skip to content

Commit 29a8e72

Browse files
Load payments in parallel using std::thread::scope
This significantly improves startup time for network-backed stores like VSS, where sequential reads incur per-key network latency.
1 parent 7dc77cc commit 29a8e72

1 file changed

Lines changed: 52 additions & 25 deletions

File tree

src/io/utils.rs

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ use lightning::ln::msgs::DecodeError;
2525
use lightning::routing::gossip::NetworkGraph;
2626
use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringDecayParameters};
2727
use lightning::util::persist::{
28-
KVSTORE_NAMESPACE_KEY_ALPHABET, KVSTORE_NAMESPACE_KEY_MAX_LEN, NETWORK_GRAPH_PERSISTENCE_KEY,
29-
NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE, NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE,
30-
OUTPUT_SWEEPER_PERSISTENCE_KEY, OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE,
31-
OUTPUT_SWEEPER_PERSISTENCE_SECONDARY_NAMESPACE, SCORER_PERSISTENCE_KEY,
32-
SCORER_PERSISTENCE_PRIMARY_NAMESPACE, SCORER_PERSISTENCE_SECONDARY_NAMESPACE,
28+
KVSTORE_NAMESPACE_KEY_ALPHABET, KVSTORE_NAMESPACE_KEY_MAX_LEN,
29+
NETWORK_GRAPH_PERSISTENCE_KEY, NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE,
30+
NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE, OUTPUT_SWEEPER_PERSISTENCE_KEY,
31+
OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE, OUTPUT_SWEEPER_PERSISTENCE_SECONDARY_NAMESPACE,
32+
SCORER_PERSISTENCE_KEY, SCORER_PERSISTENCE_PRIMARY_NAMESPACE,
33+
SCORER_PERSISTENCE_SECONDARY_NAMESPACE,
3334
};
3435
use lightning::util::ser::{Readable, ReadableArgs, Writeable};
3536
use lightning::util::string::PrintableString;
@@ -203,33 +204,59 @@ where
203204
}
204205

205206
/// Read previously persisted payments information from the store.
206-
pub(crate) fn read_payments<L: Deref>(
207+
pub(crate) fn read_payments<L: Deref + Clone + Send>(
207208
kv_store: Arc<DynStore>, logger: L,
208209
) -> Result<Vec<PaymentDetails>, std::io::Error>
209210
where
210211
L::Target: LdkLogger,
211212
{
212-
let mut res = Vec::new();
213-
214-
for stored_key in kv_store.list(
213+
let keys = kv_store.list(
215214
PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE,
216215
PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
217-
)? {
218-
let mut reader = Cursor::new(kv_store.read(
219-
PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE,
220-
PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
221-
&stored_key,
222-
)?);
223-
let payment = PaymentDetails::read(&mut reader).map_err(|e| {
224-
log_error!(logger, "Failed to deserialize PaymentDetails: {}", e);
225-
std::io::Error::new(
226-
std::io::ErrorKind::InvalidData,
227-
"Failed to deserialize PaymentDetails",
228-
)
229-
})?;
230-
res.push(payment);
231-
}
232-
Ok(res)
216+
)?;
217+
218+
// Read all payments in parallel using scoped threads.
219+
// This significantly improves performance for network-backed stores like VSS,
220+
// where sequential reads would incur per-key network latency.
221+
let results: Vec<Result<PaymentDetails, std::io::Error>> = std::thread::scope(|s| {
222+
let handles: Vec<_> = keys
223+
.iter()
224+
.map(|key| {
225+
let kv_store = Arc::clone(&kv_store);
226+
let logger = logger.clone();
227+
s.spawn(move || {
228+
let mut reader = Cursor::new(kv_store.read(
229+
PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE,
230+
PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
231+
key,
232+
)?);
233+
PaymentDetails::read(&mut reader).map_err(|e| {
234+
log_error!(logger, "Failed to deserialize PaymentDetails: {}", e);
235+
std::io::Error::new(
236+
std::io::ErrorKind::InvalidData,
237+
"Failed to deserialize PaymentDetails",
238+
)
239+
})
240+
})
241+
})
242+
.collect();
243+
244+
handles
245+
.into_iter()
246+
.map(|h| {
247+
h.join()
248+
.map_err(|_| {
249+
std::io::Error::new(
250+
std::io::ErrorKind::Other,
251+
"Thread panicked while reading payment",
252+
)
253+
})
254+
.and_then(|r| r)
255+
})
256+
.collect()
257+
});
258+
259+
results.into_iter().collect()
233260
}
234261

235262
/// Read `OutputSweeper` state from the store.

0 commit comments

Comments
 (0)