@@ -58,11 +58,14 @@ where
5858 pub ( crate ) async fn remove_peer ( & self , node_id : & PublicKey ) -> Result < ( ) , Error > {
5959 let _guard = self . mutation_lock . lock ( ) . await ;
6060 let data = {
61- let mut locked_peers = self . peers . write ( ) . expect ( "lock" ) ;
62- locked_peers. remove ( node_id) ;
63- PeerStoreSerWrapper ( & locked_peers) . encode ( )
61+ let locked_peers = self . peers . read ( ) . expect ( "lock" ) ;
62+ let mut updated_peers = locked_peers. clone ( ) ;
63+ updated_peers. remove ( node_id) ;
64+ PeerStoreSerWrapper ( & updated_peers) . encode ( )
6465 } ;
65- self . persist_peers ( data) . await
66+ self . persist_peers ( data) . await ?;
67+ self . peers . write ( ) . expect ( "lock" ) . remove ( node_id) ;
68+ Ok ( ( ) )
6669 }
6770
6871 /// Returns the current in-memory peer set.
@@ -170,12 +173,52 @@ mod tests {
170173 use std:: str:: FromStr ;
171174 use std:: sync:: Arc ;
172175
176+ use bitcoin:: io;
177+ use lightning:: util:: persist:: { PageToken , PaginatedKVStore , PaginatedListResponse } ;
173178 use lightning:: util:: test_utils:: TestLogger ;
174179
175180 use super :: * ;
176181 use crate :: io:: test_utils:: InMemoryStore ;
177182 use crate :: types:: DynStoreWrapper ;
178183
184+ struct FailingStore ;
185+
186+ impl KVStore for FailingStore {
187+ fn read (
188+ & self , _primary_namespace : & str , _secondary_namespace : & str , _key : & str ,
189+ ) -> impl std:: future:: Future < Output = Result < Vec < u8 > , io:: Error > > + ' static + Send {
190+ async { Err ( io:: Error :: new ( io:: ErrorKind :: Other , "read failed" ) ) }
191+ }
192+
193+ fn write (
194+ & self , _primary_namespace : & str , _secondary_namespace : & str , _key : & str , _buf : Vec < u8 > ,
195+ ) -> impl std:: future:: Future < Output = Result < ( ) , io:: Error > > + ' static + Send {
196+ async { Err ( io:: Error :: new ( io:: ErrorKind :: Other , "write failed" ) ) }
197+ }
198+
199+ fn remove (
200+ & self , _primary_namespace : & str , _secondary_namespace : & str , _key : & str , _lazy : bool ,
201+ ) -> impl std:: future:: Future < Output = Result < ( ) , io:: Error > > + ' static + Send {
202+ async { Err ( io:: Error :: new ( io:: ErrorKind :: Other , "remove failed" ) ) }
203+ }
204+
205+ fn list (
206+ & self , _primary_namespace : & str , _secondary_namespace : & str ,
207+ ) -> impl std:: future:: Future < Output = Result < Vec < String > , io:: Error > > + ' static + Send {
208+ async { Err ( io:: Error :: new ( io:: ErrorKind :: Other , "list failed" ) ) }
209+ }
210+ }
211+
212+ impl PaginatedKVStore for FailingStore {
213+ fn list_paginated (
214+ & self , _primary_namespace : & str , _secondary_namespace : & str ,
215+ _page_token : Option < PageToken > ,
216+ ) -> impl std:: future:: Future < Output = Result < PaginatedListResponse , io:: Error > > + ' static + Send
217+ {
218+ async { Err ( io:: Error :: new ( io:: ErrorKind :: Other , "list_paginated failed" ) ) }
219+ }
220+ }
221+
179222 #[ tokio:: test]
180223 async fn peer_info_persistence ( ) {
181224 let store: Arc < DynStore > = Arc :: new ( DynStoreWrapper ( InMemoryStore :: new ( ) ) ) ;
@@ -215,4 +258,23 @@ mod tests {
215258 assert_eq ! ( peers[ 0 ] , expected_peer_info) ;
216259 assert_eq ! ( deser_peer_store. get_peer( & node_id) , Some ( expected_peer_info) ) ;
217260 }
261+
262+ #[ tokio:: test]
263+ async fn remove_peer_does_not_mutate_memory_if_persist_fails ( ) {
264+ let store: Arc < DynStore > = Arc :: new ( DynStoreWrapper ( FailingStore ) ) ;
265+ let logger = Arc :: new ( TestLogger :: new ( ) ) ;
266+ let node_id = PublicKey :: from_str (
267+ "0276607124ebe6a6c9338517b6f485825b27c2dcc0b9fc2aa6a4c0df91194e5993" ,
268+ )
269+ . unwrap ( ) ;
270+ let peer_info =
271+ PeerInfo { node_id, address : SocketAddress :: from_str ( "127.0.0.1:9738" ) . unwrap ( ) } ;
272+ let mut peers = HashMap :: new ( ) ;
273+ peers. insert ( node_id, peer_info. clone ( ) ) ;
274+ let persisted_bytes = PeerStoreSerWrapper ( & peers) . encode ( ) ;
275+ let peer_store = PeerStore :: read ( & mut & persisted_bytes[ ..] , ( store, logger) ) . unwrap ( ) ;
276+
277+ assert_eq ! ( Err ( Error :: PersistenceFailed ) , peer_store. remove_peer( & node_id) . await ) ;
278+ assert_eq ! ( Some ( peer_info) , peer_store. get_peer( & node_id) ) ;
279+ }
218280}
0 commit comments