@@ -215,6 +215,19 @@ func queueNotification[T any](sub subscriber, recvChan chan T, ntfn T) {
215215 }
216216}
217217
218+ // dropNotification sends a best-effort notification to a subscriber.
219+ func dropNotification [T any ](sub subscriber , recvChan chan T , ntfn T ,
220+ description string ) {
221+
222+ select {
223+ case recvChan <- ntfn :
224+ case <- sub .subCtx .Done ():
225+ default :
226+ log .Debugf ("Dropping %s notification for slow subscriber" ,
227+ description )
228+ }
229+ }
230+
218231// SubscribeReservations subscribes to the reservation notifications.
219232func (m * Manager ) SubscribeReservations (ctx context.Context ,
220233) <- chan * swapserverrpc.ServerReservationNotification {
@@ -503,6 +516,66 @@ func (m *Manager) subscribeNotifications(ctx context.Context) error {
503516 }
504517}
505518
519+ // staticLoopInRiskDecisionName returns the log label for a risk decision.
520+ func staticLoopInRiskDecisionName (accepted bool ) string {
521+ if accepted {
522+ return "accepted"
523+ }
524+
525+ return "rejected"
526+ }
527+
528+ // handleStaticLoopInRiskDecision persists, caches, and forwards a risk
529+ // decision notification to the matching subscriber.
530+ func (m * Manager ) handleStaticLoopInRiskDecision (ctx context.Context ,
531+ swapHashBytes []byte , accepted bool , notifType NotificationType ,
532+ cacheDecision func (lntypes.Hash ), notifySubscriber func (subscriber )) {
533+
534+ decision := staticLoopInRiskDecisionName (accepted )
535+
536+ var (
537+ swapHash lntypes.Hash
538+ hasSwapHash bool
539+ )
540+ if swapHashBytes != nil {
541+ hash , err := lntypes .MakeHash (swapHashBytes )
542+ if err != nil {
543+ log .Warnf ("Received invalid static loop in risk " +
544+ "%s notification: %v" , decision , err )
545+ } else {
546+ swapHash = hash
547+ hasSwapHash = true
548+ }
549+ }
550+
551+ if hasSwapHash && m .cfg .PersistStaticLoopInRiskDecision != nil {
552+ err := m .cfg .PersistStaticLoopInRiskDecision (
553+ ctx , swapHash , accepted ,
554+ )
555+ if err != nil {
556+ log .Errorf ("Unable to persist static loop in risk " +
557+ "%s notification: %v" , decision , err )
558+ }
559+ }
560+
561+ m .Lock ()
562+ defer m .Unlock ()
563+
564+ if hasSwapHash {
565+ cacheDecision (swapHash )
566+ }
567+
568+ for _ , sub := range m .subscribers [notifType ] {
569+ if ! hasSwapHash || sub .swapHash == nil ||
570+ * sub .swapHash != swapHash {
571+
572+ continue
573+ }
574+
575+ notifySubscriber (sub )
576+ }
577+ }
578+
506579// handleNotification handles an incoming notification from the server,
507580// forwarding it to the appropriate subscribers.
508581func (m * Manager ) handleNotification (ctx context.Context , ntfn * swapserverrpc.
@@ -545,115 +618,55 @@ func (m *Manager) handleNotification(ctx context.Context, ntfn *swapserverrpc.
545618 // We'll forward the static loop in risk accepted notification to the
546619 // subscriber for the matching swap.
547620 riskAcceptedNtfn := ntfn .GetStaticLoopInRiskAccepted ()
548- var (
549- swapHash lntypes.Hash
550- hasSwapHash bool
551- )
621+ var swapHashBytes []byte
552622 if riskAcceptedNtfn != nil {
553- hash , err := lntypes .MakeHash (riskAcceptedNtfn .SwapHash )
554- if err != nil {
555- log .Warnf ("Received invalid static loop in risk " +
556- "accepted notification: %v" , err )
557- } else {
558- swapHash = hash
559- hasSwapHash = true
560- }
561- }
562-
563- if hasSwapHash && m .cfg .PersistStaticLoopInRiskDecision != nil {
564- err := m .cfg .PersistStaticLoopInRiskDecision (
565- ctx , swapHash , true ,
566- )
567- if err != nil {
568- log .Errorf ("Unable to persist static loop in " +
569- "risk accepted notification: %v" , err )
570- }
623+ swapHashBytes = riskAcceptedNtfn .SwapHash
571624 }
572625
573- m .Lock ()
574- defer m .Unlock ()
575-
576- if hasSwapHash {
577- m .staticLoopInRiskAccepted [swapHash ] =
578- riskAcceptedNtfn
579- delete (m .staticLoopInRiskRejected , swapHash )
580- }
581-
582- for _ , sub := range m .subscribers [NotificationTypeStaticLoopInRiskAccepted ] { // nolint: lll
583- if ! hasSwapHash || sub .swapHash == nil ||
584- * sub .swapHash != swapHash {
585-
586- continue
587- }
588-
589- recvChan := sub .recvChan .(chan * swapserverrpc.
590- ServerStaticLoopInRiskAcceptedNotification )
591-
592- select {
593- case recvChan <- riskAcceptedNtfn :
594- case <- sub .subCtx .Done ():
595- default :
596- log .Debugf ("Dropping static loop in risk " +
597- "accepted notification for slow subscriber" )
598- }
599- }
626+ m .handleStaticLoopInRiskDecision (
627+ ctx , swapHashBytes , true ,
628+ NotificationTypeStaticLoopInRiskAccepted ,
629+ func (swapHash lntypes.Hash ) {
630+ m .staticLoopInRiskAccepted [swapHash ] =
631+ riskAcceptedNtfn
632+ delete (m .staticLoopInRiskRejected , swapHash )
633+ },
634+ func (sub subscriber ) {
635+ recvChan := sub .recvChan .(chan * swapserverrpc.
636+ ServerStaticLoopInRiskAcceptedNotification )
637+ dropNotification (
638+ sub , recvChan , riskAcceptedNtfn ,
639+ "static loop in risk accepted" ,
640+ )
641+ },
642+ )
600643
601644 case * swapserverrpc.SubscribeNotificationsResponse_StaticLoopInRiskRejected : // nolint: lll
602645 // We'll forward the static loop in risk rejected notification to the
603646 // subscriber for the matching swap.
604647 riskRejectedNtfn := ntfn .GetStaticLoopInRiskRejected ()
605- var (
606- swapHash lntypes.Hash
607- hasSwapHash bool
608- )
648+ var swapHashBytes []byte
609649 if riskRejectedNtfn != nil {
610- hash , err := lntypes .MakeHash (riskRejectedNtfn .SwapHash )
611- if err != nil {
612- log .Warnf ("Received invalid static loop in risk " +
613- "rejected notification: %v" , err )
614- } else {
615- swapHash = hash
616- hasSwapHash = true
617- }
650+ swapHashBytes = riskRejectedNtfn .SwapHash
618651 }
619652
620- if hasSwapHash && m .cfg .PersistStaticLoopInRiskDecision != nil {
621- err := m .cfg .PersistStaticLoopInRiskDecision (
622- ctx , swapHash , false ,
623- )
624- if err != nil {
625- log .Errorf ("Unable to persist static loop in " +
626- "risk rejected notification: %v" , err )
627- }
628- }
629-
630- m .Lock ()
631- defer m .Unlock ()
632-
633- if hasSwapHash {
634- m .staticLoopInRiskRejected [swapHash ] =
635- riskRejectedNtfn
636- delete (m .staticLoopInRiskAccepted , swapHash )
637- }
638-
639- for _ , sub := range m .subscribers [NotificationTypeStaticLoopInRiskRejected ] { // nolint: lll
640- if ! hasSwapHash || sub .swapHash == nil ||
641- * sub .swapHash != swapHash {
642-
643- continue
644- }
645-
646- recvChan := sub .recvChan .(chan * swapserverrpc.
647- ServerStaticLoopInRiskRejectedNotification )
648-
649- select {
650- case recvChan <- riskRejectedNtfn :
651- case <- sub .subCtx .Done ():
652- default :
653- log .Debugf ("Dropping static loop in risk " +
654- "rejected notification for slow subscriber" )
655- }
656- }
653+ m .handleStaticLoopInRiskDecision (
654+ ctx , swapHashBytes , false ,
655+ NotificationTypeStaticLoopInRiskRejected ,
656+ func (swapHash lntypes.Hash ) {
657+ m .staticLoopInRiskRejected [swapHash ] =
658+ riskRejectedNtfn
659+ delete (m .staticLoopInRiskAccepted , swapHash )
660+ },
661+ func (sub subscriber ) {
662+ recvChan := sub .recvChan .(chan * swapserverrpc.
663+ ServerStaticLoopInRiskRejectedNotification )
664+ dropNotification (
665+ sub , recvChan , riskRejectedNtfn ,
666+ "static loop in risk rejected" ,
667+ )
668+ },
669+ )
657670
658671 case * swapserverrpc.SubscribeNotificationsResponse_UnfinishedSwap : // nolint: lll
659672 // We'll forward the unfinished swap notification to all
0 commit comments