@@ -56,6 +56,12 @@ impl PeerState {
56
56
pending_remove_webhook_requests : BoundedMap :: new ( MAX_PENDING_REQUESTS ) ,
57
57
}
58
58
}
59
+
60
+ fn is_empty ( & self ) -> bool {
61
+ self . pending_set_webhook_requests . is_empty ( )
62
+ && self . pending_list_webhooks_requests . is_empty ( )
63
+ && self . pending_remove_webhook_requests . is_empty ( )
64
+ }
59
65
}
60
66
61
67
/// Client-side handler for the LSPS5 (bLIP-55) webhook registration protocol.
@@ -345,6 +351,19 @@ where
345
351
}
346
352
} ;
347
353
self . with_peer_state ( * counterparty_node_id, handle_response) ;
354
+
355
+ let mut outer_state_lock = self . per_peer_state . write ( ) . unwrap ( ) ;
356
+ let should_remove =
357
+ if let Some ( peer_state_mutex) = outer_state_lock. get ( counterparty_node_id) {
358
+ let peer_state = peer_state_mutex. lock ( ) . unwrap ( ) ;
359
+ peer_state. is_empty ( )
360
+ } else {
361
+ false
362
+ } ;
363
+
364
+ if should_remove {
365
+ outer_state_lock. remove ( counterparty_node_id) ;
366
+ }
348
367
result
349
368
}
350
369
}
@@ -461,36 +480,6 @@ mod tests {
461
480
}
462
481
}
463
482
464
- #[ test]
465
- fn test_handle_response_clears_pending_state ( ) {
466
- let ( client, _, _, peer, _) = setup_test_client ( ) ;
467
-
468
- let req_id = client
469
- . set_webhook ( peer, "test-app" . to_string ( ) , "https://example.com/hook" . to_string ( ) )
470
- . unwrap ( ) ;
471
-
472
- let response = LSPS5Response :: SetWebhook ( SetWebhookResponse {
473
- num_webhooks : 1 ,
474
- max_webhooks : 5 ,
475
- no_change : false ,
476
- } ) ;
477
- let response_msg = LSPS5Message :: Response ( req_id. clone ( ) , response) ;
478
-
479
- {
480
- let outer_state_lock = client. per_peer_state . read ( ) . unwrap ( ) ;
481
- let peer_state = outer_state_lock. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
482
- assert ! ( peer_state. pending_set_webhook_requests. contains_key( & req_id) ) ;
483
- }
484
-
485
- client. handle_message ( response_msg, & peer) . unwrap ( ) ;
486
-
487
- {
488
- let outer_state_lock = client. per_peer_state . read ( ) . unwrap ( ) ;
489
- let peer_state = outer_state_lock. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
490
- assert ! ( !peer_state. pending_set_webhook_requests. contains_key( & req_id) ) ;
491
- }
492
- }
493
-
494
483
#[ test]
495
484
fn test_unknown_request_id_handling ( ) {
496
485
let ( client, _message_queue, _, peer, _) = setup_test_client ( ) ;
@@ -552,4 +541,68 @@ mod tests {
552
541
assert ! ( peer_state. pending_set_webhook_requests. contains_key( & new_req_id) ) ;
553
542
}
554
543
}
544
+
545
+ #[ test]
546
+ fn test_peer_state_cleanup_and_recreation ( ) {
547
+ let ( client, _, _, peer, _) = setup_test_client ( ) ;
548
+
549
+ let set_webhook_req_id = client
550
+ . set_webhook ( peer, "test-app" . to_string ( ) , "https://example.com/hook" . to_string ( ) )
551
+ . unwrap ( ) ;
552
+
553
+ let list_webhooks_req_id = client. list_webhooks ( peer) ;
554
+
555
+ {
556
+ let state = client. per_peer_state . read ( ) . unwrap ( ) ;
557
+ assert ! ( state. contains_key( & peer) ) ;
558
+ let peer_state = state. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
559
+ assert ! ( peer_state. pending_set_webhook_requests. contains_key( & set_webhook_req_id) ) ;
560
+ assert ! ( peer_state. pending_list_webhooks_requests. contains_key( & list_webhooks_req_id) ) ;
561
+ }
562
+
563
+ let set_webhook_response = LSPS5Response :: SetWebhook ( SetWebhookResponse {
564
+ num_webhooks : 1 ,
565
+ max_webhooks : 5 ,
566
+ no_change : false ,
567
+ } ) ;
568
+ let response_msg = LSPS5Message :: Response ( set_webhook_req_id. clone ( ) , set_webhook_response) ;
569
+ // trigger cleanup but there is still a pending request
570
+ // so the peer state should not be removed
571
+ client. handle_message ( response_msg, & peer) . unwrap ( ) ;
572
+
573
+ {
574
+ let state = client. per_peer_state . read ( ) . unwrap ( ) ;
575
+ assert ! ( state. contains_key( & peer) ) ;
576
+ let peer_state = state. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
577
+ assert ! ( !peer_state. pending_set_webhook_requests. contains_key( & set_webhook_req_id) ) ;
578
+ assert ! ( peer_state. pending_list_webhooks_requests. contains_key( & list_webhooks_req_id) ) ;
579
+ }
580
+
581
+ let list_webhooks_response =
582
+ LSPS5Response :: ListWebhooks ( crate :: lsps5:: msgs:: ListWebhooksResponse {
583
+ app_names : vec ! [ ] ,
584
+ max_webhooks : 5 ,
585
+ } ) ;
586
+ let response_msg = LSPS5Message :: Response ( list_webhooks_req_id, list_webhooks_response) ;
587
+
588
+ // now the pending request is handled, so the peer state should be removed
589
+ client. handle_message ( response_msg, & peer) . unwrap ( ) ;
590
+
591
+ {
592
+ let state = client. per_peer_state . read ( ) . unwrap ( ) ;
593
+ assert ! ( !state. contains_key( & peer) ) ;
594
+ }
595
+
596
+ // check that it's possible to recreate the peer state by sending a new request
597
+ let new_req_id = client
598
+ . set_webhook ( peer, "test-app-2" . to_string ( ) , "https://example.com/hook2" . to_string ( ) )
599
+ . unwrap ( ) ;
600
+
601
+ {
602
+ let state = client. per_peer_state . read ( ) . unwrap ( ) ;
603
+ assert ! ( state. contains_key( & peer) ) ;
604
+ let peer_state = state. get ( & peer) . unwrap ( ) . lock ( ) . unwrap ( ) ;
605
+ assert ! ( peer_state. pending_set_webhook_requests. contains_key( & new_req_id) ) ;
606
+ }
607
+ }
555
608
}
0 commit comments