@@ -65,6 +65,34 @@ pub(crate) enum WalletSyncStatus {
6565 InProgress { subscribers : tokio:: sync:: broadcast:: Sender < Result < ( ) , Error > > } ,
6666}
6767
68+ pub ( crate ) struct WalletSyncGuard < ' a > {
69+ status : & ' a Mutex < WalletSyncStatus > ,
70+ cancellation_error : Error ,
71+ active : bool ,
72+ }
73+
74+ impl < ' a > WalletSyncGuard < ' a > {
75+ pub ( crate ) fn new ( status : & ' a Mutex < WalletSyncStatus > , cancellation_error : Error ) -> Self {
76+ Self { status, cancellation_error, active : true }
77+ }
78+
79+ pub ( crate ) fn complete ( mut self , res : Result < ( ) , Error > ) {
80+ self . status . lock ( ) . expect ( "lock" ) . propagate_result_to_subscribers ( res) ;
81+ self . active = false ;
82+ }
83+ }
84+
85+ impl Drop for WalletSyncGuard < ' _ > {
86+ fn drop ( & mut self ) {
87+ if self . active {
88+ self . status
89+ . lock ( )
90+ . expect ( "lock" )
91+ . propagate_result_to_subscribers ( Err ( self . cancellation_error ) ) ;
92+ }
93+ }
94+ }
95+
6896impl WalletSyncStatus {
6997 fn register_or_subscribe_pending_sync (
7098 & mut self ,
@@ -95,16 +123,7 @@ impl WalletSyncStatus {
95123 WalletSyncStatus :: InProgress { subscribers } => {
96124 // A sync is in-progress, we notify subscribers.
97125 if subscribers. receiver_count ( ) > 0 {
98- match subscribers. send ( res) {
99- Ok ( _) => ( ) ,
100- Err ( e) => {
101- debug_assert ! (
102- false ,
103- "Failed to send wallet sync result to subscribers: {:?}" ,
104- e
105- ) ;
106- } ,
107- }
126+ let _ = subscribers. send ( res) ;
108127 }
109128 * self = WalletSyncStatus :: Completed ;
110129 } ,
@@ -561,3 +580,28 @@ impl Filter for ChainSource {
561580 }
562581 }
563582}
583+
584+ #[ cfg( test) ]
585+ mod tests {
586+ use super :: * ;
587+
588+ #[ test]
589+ fn wallet_sync_guard_resets_abandoned_sync ( ) {
590+ let status = Mutex :: new ( WalletSyncStatus :: Completed ) ;
591+ assert ! ( status. lock( ) . expect( "lock" ) . register_or_subscribe_pending_sync( ) . is_none( ) ) ;
592+ let sync_guard = WalletSyncGuard :: new ( & status, Error :: WalletOperationFailed ) ;
593+ let mut subscriber = status
594+ . lock ( )
595+ . expect ( "lock" )
596+ . register_or_subscribe_pending_sync ( )
597+ . expect ( "sync subscriber" ) ;
598+
599+ drop ( sync_guard) ;
600+
601+ assert ! (
602+ matches!( * status. lock( ) . expect( "lock" ) , WalletSyncStatus :: Completed ) ,
603+ "abandoned wallet sync should reset its status"
604+ ) ;
605+ assert_eq ! ( subscriber. try_recv( ) , Ok ( Err ( Error :: WalletOperationFailed ) ) ) ;
606+ }
607+ }
0 commit comments