Skip to content

Commit 9c69063

Browse files
committed
lsps2: Retry failed lease negotiation
Retry transient LSPS2 request failures for foreground acquisition and background cache refills. Preserve immediate errors for fee limits and unavailable liquidity sources. Co-Authored-By: HAL 9000
1 parent 3892be4 commit 9c69063

1 file changed

Lines changed: 69 additions & 0 deletions

File tree

  • src/liquidity/client/lsps2

src/liquidity/client/lsps2/mod.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ where
5858
}
5959

6060
const DEFAULT_BOLT12_INVOICE_EXPIRY_SECS: u32 = 2 * 60 * 60;
61+
const LEASE_NEGOTIATION_MAX_ATTEMPTS: usize = 3;
62+
63+
fn should_retry_lease_negotiation(error: Error, attempt: usize) -> bool {
64+
error == Error::LiquidityRequestFailed && attempt < LEASE_NEGOTIATION_MAX_ATTEMPTS
65+
}
6166

6267
pub(crate) struct JitInvoiceResponse {
6368
pub(crate) payment_metadata: BTreeMap<u64, Vec<u8>>,
@@ -323,6 +328,34 @@ where
323328

324329
async fn negotiate_fixed_lease(
325330
self: &Arc<Self>, amount_msat: u64, connection_manager: &Arc<ConnectionManager<L>>,
331+
) -> Result<(PaymentLease, u64, LspConfig), Error> {
332+
let mut attempt = 1;
333+
loop {
334+
let result = self
335+
.negotiate_fixed_lease_once(
336+
amount_msat,
337+
max_total_lsp_fee_limit_msat,
338+
connection_manager,
339+
)
340+
.await;
341+
match result {
342+
Err(error) if should_retry_lease_negotiation(error, attempt) => {
343+
log_warn!(
344+
self.logger,
345+
"LSPS2 lease negotiation attempt {} failed, retrying: {}",
346+
attempt,
347+
error
348+
);
349+
attempt += 1;
350+
},
351+
result => return result,
352+
}
353+
}
354+
}
355+
356+
async fn negotiate_fixed_lease_once(
357+
self: &Arc<Self>, amount_msat: u64, max_total_lsp_fee_limit_msat: Option<u64>,
358+
connection_manager: &Arc<ConnectionManager<L>>,
326359
) -> Result<(PaymentLease, u64, LspConfig), Error> {
327360
let all_offers = self.gather_lsps2_offers(connection_manager).await?;
328361
let (cheapest_lsp, min_total_fee_msat, min_opening_params) = all_offers
@@ -409,6 +442,33 @@ where
409442

410443
async fn negotiate_variable_lease(
411444
self: &Arc<Self>, connection_manager: &Arc<ConnectionManager<L>>,
445+
) -> Result<(PaymentLease, u64, LspConfig), Error> {
446+
let mut attempt = 1;
447+
loop {
448+
let result = self
449+
.negotiate_variable_lease_once(
450+
max_proportional_lsp_fee_limit_ppm_msat,
451+
connection_manager,
452+
)
453+
.await;
454+
match result {
455+
Err(error) if should_retry_lease_negotiation(error, attempt) => {
456+
log_warn!(
457+
self.logger,
458+
"LSPS2 lease negotiation attempt {} failed, retrying: {}",
459+
attempt,
460+
error
461+
);
462+
attempt += 1;
463+
},
464+
result => return result,
465+
}
466+
}
467+
}
468+
469+
async fn negotiate_variable_lease_once(
470+
self: &Arc<Self>, max_proportional_lsp_fee_limit_ppm_msat: Option<u64>,
471+
connection_manager: &Arc<ConnectionManager<L>>,
412472
) -> Result<(PaymentLease, u64, LspConfig), Error> {
413473
let all_offers = self.gather_lsps2_offers(connection_manager).await?;
414474
let mut rejected_for_fee = false;
@@ -981,6 +1041,15 @@ mod tests {
9811041
assert_eq!(result, Err(()));
9821042
assert!(!*consumed.lock().unwrap());
9831043
}
1044+
1045+
#[test]
1046+
fn lease_negotiation_retries_only_transient_failures() {
1047+
assert!(should_retry_lease_negotiation(Error::LiquidityRequestFailed, 1));
1048+
assert!(should_retry_lease_negotiation(Error::LiquidityRequestFailed, 2));
1049+
assert!(!should_retry_lease_negotiation(Error::LiquidityRequestFailed, 3));
1050+
assert!(!should_retry_lease_negotiation(Error::LiquidityFeeTooHigh, 1));
1051+
assert!(!should_retry_lease_negotiation(Error::LiquiditySourceUnavailable, 1));
1052+
}
9841053
}
9851054

9861055
pub(crate) mod router;

0 commit comments

Comments
 (0)