@@ -1349,12 +1349,31 @@ impl<MR: MessageRouter, L: Logger> OffersMessageFlow<MR, L> {
13491349 self . check_refresh_async_offers ( peers. clone ( ) , timer_tick_occurred) ?;
13501350
13511351 if timer_tick_occurred {
1352- self . check_refresh_static_invoices ( peers, usable_channels, router) ;
1352+ self . check_refresh_static_invoices ( peers, usable_channels, router, false ) ;
13531353 }
13541354
13551355 Ok ( ( ) )
13561356 }
13571357
1358+ /// Enqueues static invoice updates for cached async receive offers after local channel changes.
1359+ pub fn force_refresh_async_receive_static_invoices < R : Router , F > (
1360+ & self , get_refresh_inputs : F , router : R ,
1361+ ) where
1362+ F : FnOnce ( ) -> ( Vec < MessageForwardNode > , Vec < ChannelDetails > ) ,
1363+ {
1364+ // A forced refresh is useful only for an async recipient already configured with a server.
1365+ let cache = self . async_receive_offer_cache . lock ( ) . unwrap ( ) ;
1366+ if cache. paths_to_static_invoice_server ( ) . is_empty ( ) {
1367+ return ;
1368+ }
1369+ core:: mem:: drop ( cache) ;
1370+
1371+ // Channel details may be in a short-lived transitional state when this refresh is requested.
1372+ // Collect them only after confirming that async receiving needs the snapshot.
1373+ let ( peers, usable_channels) = get_refresh_inputs ( ) ;
1374+ self . check_refresh_static_invoices ( peers, usable_channels, router, true ) ;
1375+ }
1376+
13581377 fn check_refresh_async_offers (
13591378 & self , peers : Vec < MessageForwardNode > , timer_tick_occurred : bool ,
13601379 ) -> Result < ( ) , ( ) > {
@@ -1408,41 +1427,59 @@ impl<MR: MessageRouter, L: Logger> OffersMessageFlow<MR, L> {
14081427 /// server, based on the offers provided by the cache.
14091428 fn check_refresh_static_invoices < R : Router > (
14101429 & self , peers : Vec < MessageForwardNode > , usable_channels : Vec < ChannelDetails > , router : R ,
1430+ force_refresh : bool ,
14111431 ) {
14121432 let mut serve_static_invoice_msgs = Vec :: new ( ) ;
14131433 {
14141434 let duration_since_epoch = self . duration_since_epoch ( ) ;
14151435 let cache = self . async_receive_offer_cache . lock ( ) . unwrap ( ) ;
1416- for offer_and_metadata in cache. offers_needing_invoice_refresh ( duration_since_epoch) {
1417- let ( offer, offer_nonce, update_static_invoice_path) = offer_and_metadata;
1418-
1419- let ( invoice, forward_invreq_path) = match self . create_static_invoice_for_server (
1420- offer,
1421- offer_nonce,
1422- peers. clone ( ) ,
1423- usable_channels. clone ( ) ,
1424- & router,
1425- ) {
1426- Ok ( ( invoice, path) ) => ( invoice, path) ,
1427- Err ( ( ) ) => continue ,
1428- } ;
14291436
1430- let reply_path_context = {
1431- MessageContext :: AsyncPayments ( AsyncPaymentsContext :: StaticInvoicePersisted {
1432- invoice_created_at : invoice. created_at ( ) ,
1433- offer_id : offer. id ( ) ,
1434- } )
1435- } ;
1437+ // Both timer-driven and forced refreshes build the same update message. Keep the
1438+ // construction in one place so the only difference is which cached offers are selected.
1439+ macro_rules! build_refresh_message {
1440+ ( $offer: expr, $offer_nonce: expr, $update_static_invoice_path: expr) => { {
1441+ let ( invoice, forward_invreq_path) = match self
1442+ . create_static_invoice_for_server(
1443+ $offer,
1444+ $offer_nonce,
1445+ peers. clone( ) ,
1446+ usable_channels. clone( ) ,
1447+ & router,
1448+ ) {
1449+ Ok ( ( invoice, path) ) => ( invoice, path) ,
1450+ Err ( ( ) ) => continue ,
1451+ } ;
1452+
1453+ let reply_path_context = MessageContext :: AsyncPayments (
1454+ AsyncPaymentsContext :: StaticInvoicePersisted {
1455+ invoice_created_at: invoice. created_at( ) ,
1456+ offer_id: $offer. id( ) ,
1457+ } ,
1458+ ) ;
14361459
1437- let serve_invoice_message = ServeStaticInvoice {
1438- invoice,
1439- forward_invoice_request_path : forward_invreq_path,
1440- } ;
1441- serve_static_invoice_msgs. push ( (
1442- serve_invoice_message,
1443- update_static_invoice_path. clone ( ) ,
1444- reply_path_context,
1445- ) ) ;
1460+ let serve_invoice_message = ServeStaticInvoice {
1461+ invoice,
1462+ forward_invoice_request_path: forward_invreq_path,
1463+ } ;
1464+ serve_static_invoice_msgs. push( (
1465+ serve_invoice_message,
1466+ $update_static_invoice_path. clone( ) ,
1467+ reply_path_context,
1468+ ) ) ;
1469+ } } ;
1470+ }
1471+
1472+ if force_refresh {
1473+ for offer_and_metadata in cache. offers_needing_forced_invoice_refresh ( ) {
1474+ let ( offer, offer_nonce, update_static_invoice_path) = offer_and_metadata;
1475+ build_refresh_message ! ( offer, offer_nonce, update_static_invoice_path) ;
1476+ }
1477+ } else {
1478+ for offer_and_metadata in cache. offers_needing_invoice_refresh ( duration_since_epoch)
1479+ {
1480+ let ( offer, offer_nonce, update_static_invoice_path) = offer_and_metadata;
1481+ build_refresh_message ! ( offer, offer_nonce, update_static_invoice_path) ;
1482+ }
14461483 }
14471484 }
14481485
0 commit comments