@@ -12,7 +12,9 @@ use std::sync::atomic::{AtomicU64, Ordering};
1212use std:: sync:: { Arc , Mutex } ;
1313
1414use lightning:: io;
15- use lightning:: util:: persist:: { KVStore , PageToken , PaginatedKVStore , PaginatedListResponse } ;
15+ use lightning:: util:: persist:: {
16+ KVStore , MigratableKVStore , PageToken , PaginatedKVStore , PaginatedListResponse ,
17+ } ;
1618use lightning_types:: string:: PrintableString ;
1719use native_tls:: TlsConnector ;
1820use postgres_native_tls:: MakeTlsConnector ;
@@ -351,6 +353,24 @@ impl PaginatedKVStore for PostgresStore {
351353 }
352354}
353355
356+ impl MigratableKVStore for PostgresStore {
357+ fn list_all_keys (
358+ & self ,
359+ ) -> impl Future < Output = Result < Vec < ( String , String , String ) > , io:: Error > > + ' static + Send {
360+ let inner = Arc :: clone ( & self . inner ) ;
361+ let runtime = self . internal_runtime ( ) ;
362+ async move {
363+ let task = runtime. spawn ( async move { inner. list_all_keys_internal ( ) . await } ) ;
364+ task. await . map_err ( |e| {
365+ io:: Error :: new (
366+ io:: ErrorKind :: Other ,
367+ format ! ( "PostgreSQL runtime task failed: {}" , e) ,
368+ )
369+ } ) ?
370+ }
371+ }
372+ }
373+
354374struct PostgresStoreInner {
355375 pool : SmallPool ,
356376 config : Config ,
@@ -725,6 +745,25 @@ impl PostgresStoreInner {
725745 Ok ( keys)
726746 }
727747
748+ async fn list_all_keys_internal ( & self ) -> io:: Result < Vec < ( String , String , String ) > > {
749+ let sql = format ! (
750+ "SELECT primary_namespace, secondary_namespace, key FROM {}" ,
751+ self . kv_table_name_sql
752+ ) ;
753+
754+ let err_map = |e : PgError | {
755+ let msg = format ! ( "Failed to retrieve queried rows: {e}" ) ;
756+ io:: Error :: new ( io:: ErrorKind :: Other , msg)
757+ } ;
758+
759+ let mut locked = self . locked_client ( ) . await ?;
760+ let rows = query_with_retry ! ( self , locked, err_map, locked. query( sql. as_str( ) , & [ ] ) ) ?;
761+
762+ let keys: Vec < ( String , String , String ) > =
763+ rows. iter ( ) . map ( |row| ( row. get ( 0 ) , row. get ( 1 ) , row. get ( 2 ) ) ) . collect ( ) ;
764+ Ok ( keys)
765+ }
766+
728767 async fn list_paginated_internal (
729768 & self , primary_namespace : & str , secondary_namespace : & str , page_token : Option < PageToken > ,
730769 ) -> io:: Result < PaginatedListResponse > {
@@ -904,6 +943,29 @@ mod tests {
904943 cleanup_store ( & store_1) . await ;
905944 }
906945
946+ #[ tokio:: test( flavor = "multi_thread" ) ]
947+ async fn test_postgres_store_list_all_keys ( ) {
948+ let store = create_test_store ( "test_pg_list_all_keys" ) . await ;
949+
950+ KVStore :: write ( & store, "ns_a" , "sub_a" , "key_a" , vec ! [ 1u8 ] ) . await . unwrap ( ) ;
951+ KVStore :: write ( & store, "ns_a" , "sub_b" , "key_b" , vec ! [ 2u8 ] ) . await . unwrap ( ) ;
952+ KVStore :: write ( & store, "ns_b" , "" , "key_c" , vec ! [ 3u8 ] ) . await . unwrap ( ) ;
953+
954+ let mut keys = MigratableKVStore :: list_all_keys ( & store) . await . unwrap ( ) ;
955+ keys. sort ( ) ;
956+
957+ assert_eq ! (
958+ keys,
959+ vec![
960+ ( "ns_a" . to_string( ) , "sub_a" . to_string( ) , "key_a" . to_string( ) ) ,
961+ ( "ns_a" . to_string( ) , "sub_b" . to_string( ) , "key_b" . to_string( ) ) ,
962+ ( "ns_b" . to_string( ) , "" . to_string( ) , "key_c" . to_string( ) ) ,
963+ ]
964+ ) ;
965+
966+ cleanup_store ( & store) . await ;
967+ }
968+
907969 async fn kill_connection ( store : & PostgresStore ) {
908970 // Terminate every backend in the pool so the next op deterministically
909971 // hits a closed connection regardless of which slot `get` selects.
0 commit comments