@@ -112,9 +112,19 @@ where
112112 }
113113
114114 pub ( crate ) async fn remove ( & self , id : & SO :: Id ) -> Result < ( ) , Error > {
115+ self . remove_batch ( std:: slice:: from_ref ( id) ) . await ?;
116+ Ok ( ( ) )
117+ }
118+
119+ pub ( crate ) async fn remove_batch ( & self , ids : & [ SO :: Id ] ) -> Result < Vec < SO > , Error > {
115120 let _guard = self . mutation_lock . lock ( ) . await ;
116- let should_remove = { self . objects . lock ( ) . expect ( "lock" ) . contains_key ( id) } ;
117- if should_remove {
121+ let mut removed_objects = Vec :: new ( ) ;
122+ for id in ids {
123+ let should_remove = { self . objects . lock ( ) . expect ( "lock" ) . contains_key ( id) } ;
124+ if !should_remove {
125+ continue ;
126+ }
127+
118128 let store_key = id. encode_to_hex_str ( ) ;
119129 KVStore :: remove (
120130 & * self . kv_store ,
@@ -135,9 +145,12 @@ where
135145 ) ;
136146 Error :: PersistenceFailed
137147 } ) ?;
138- self . objects . lock ( ) . expect ( "lock" ) . remove ( id) ;
148+
149+ if let Some ( object) = self . objects . lock ( ) . expect ( "lock" ) . remove ( id) {
150+ removed_objects. push ( object) ;
151+ }
139152 }
140- Ok ( ( ) )
153+ Ok ( removed_objects )
141154 }
142155
143156 /// Returns the current in-memory object for `id`.
@@ -422,6 +435,45 @@ mod tests {
422435 assert ! ( data_store. get( & new_id) . is_none( ) ) ;
423436 }
424437
438+ #[ tokio:: test]
439+ async fn batch_remove_removes_persisted_objects ( ) {
440+ let store: Arc < DynStore > = Arc :: new ( DynStoreWrapper ( InMemoryStore :: new ( ) ) ) ;
441+ let logger = Arc :: new ( TestLogger :: new ( ) ) ;
442+ let primary_namespace = "datastore_batch_remove_test_primary" . to_string ( ) ;
443+ let secondary_namespace = "datastore_batch_remove_test_secondary" . to_string ( ) ;
444+ let data_store: DataStore < TestObject , Arc < TestLogger > > = DataStore :: new (
445+ Vec :: new ( ) ,
446+ primary_namespace. clone ( ) ,
447+ secondary_namespace. clone ( ) ,
448+ Arc :: clone ( & store) ,
449+ logger,
450+ ) ;
451+
452+ let first = TestObject { id : TestObjectId { id : [ 1u8 ; 4 ] } , data : [ 23u8 ; 3 ] } ;
453+ let second = TestObject { id : TestObjectId { id : [ 2u8 ; 4 ] } , data : [ 42u8 ; 3 ] } ;
454+ let missing_id = TestObjectId { id : [ 3u8 ; 4 ] } ;
455+ assert_eq ! ( Ok ( false ) , data_store. insert( first) . await ) ;
456+ assert_eq ! ( Ok ( false ) , data_store. insert( second) . await ) ;
457+
458+ assert_eq ! (
459+ Ok ( vec![ first, second] ) ,
460+ data_store. remove_batch( & [ first. id, missing_id, second. id] ) . await
461+ ) ;
462+ assert_eq ! ( None , data_store. get( & first. id) ) ;
463+ assert_eq ! ( None , data_store. get( & second. id) ) ;
464+
465+ for id in [ first. id , second. id ] {
466+ assert ! ( KVStore :: read(
467+ & * store,
468+ & primary_namespace,
469+ & secondary_namespace,
470+ & id. encode_to_hex_str( )
471+ )
472+ . await
473+ . is_err( ) ) ;
474+ }
475+ }
476+
425477 #[ tokio:: test]
426478 async fn insert_does_not_mutate_memory_if_persist_fails ( ) {
427479 let id = TestObjectId { id : [ 42u8 ; 4 ] } ;
0 commit comments