@@ -567,6 +567,128 @@ pub trait MigratableKVStoreSync: KVStoreSync {
567567 fn list_all_keys ( & self ) -> Result < Vec < ( String , String , String ) > , io:: Error > ;
568568}
569569
570+ /// Provides additional interface methods that are required for [`KVStore`]-to-[`KVStore`]
571+ /// data migration.
572+ ///
573+ /// This is not exported to bindings users as async is only supported in Rust.
574+ pub trait MigratableKVStore : KVStore {
575+ /// Returns *all* known keys as a list of `primary_namespace`, `secondary_namespace`, `key` tuples.
576+ ///
577+ /// This is useful for migrating data from [`KVStore`] implementation to [`KVStore`]
578+ /// implementation.
579+ ///
580+ /// Must exhaustively return all entries known to the store to ensure no data is missed, but
581+ /// may return the items in arbitrary order.
582+ fn list_all_keys (
583+ & self ,
584+ ) -> impl Future < Output = Result < Vec < ( String , String , String ) > , io:: Error > > + ' static + MaybeSend ;
585+ }
586+
587+ impl < K > MigratableKVStore for K
588+ where
589+ K : Deref ,
590+ K :: Target : MigratableKVStore ,
591+ {
592+ fn list_all_keys (
593+ & self ,
594+ ) -> impl Future < Output = Result < Vec < ( String , String , String ) > , io:: Error > > + ' static + MaybeSend
595+ {
596+ self . deref ( ) . list_all_keys ( )
597+ }
598+ }
599+
600+ /// This is not exported to bindings users as async is only supported in Rust.
601+ impl < K : Deref > MigratableKVStore for KVStoreSyncWrapper < K >
602+ where
603+ K :: Target : MigratableKVStoreSync ,
604+ {
605+ fn list_all_keys (
606+ & self ,
607+ ) -> impl Future < Output = Result < Vec < ( String , String , String ) > , io:: Error > > + ' static + MaybeSend
608+ {
609+ let res = self . 0 . list_all_keys ( ) ;
610+
611+ async move { res }
612+ }
613+ }
614+
615+ type MigrationKey = ( String , String , String ) ;
616+
617+ trait MigrationKVStore {
618+ fn list_all_keys (
619+ & self ,
620+ ) -> impl Future < Output = Result < Vec < MigrationKey > , io:: Error > > + MaybeSend ;
621+ fn read (
622+ & self , primary_namespace : & str , secondary_namespace : & str , key : & str ,
623+ ) -> impl Future < Output = Result < Vec < u8 > , io:: Error > > + MaybeSend ;
624+ fn write (
625+ & self , primary_namespace : & str , secondary_namespace : & str , key : & str , buf : Vec < u8 > ,
626+ ) -> impl Future < Output = Result < ( ) , io:: Error > > + MaybeSend ;
627+ }
628+
629+ struct MigrationKVStoreSyncAdapter < ' a , K : ?Sized > ( & ' a K ) ;
630+
631+ impl < K : MigratableKVStoreSync + ?Sized > MigrationKVStore for MigrationKVStoreSyncAdapter < ' _ , K > {
632+ fn list_all_keys (
633+ & self ,
634+ ) -> impl Future < Output = Result < Vec < MigrationKey > , io:: Error > > + MaybeSend {
635+ let res = MigratableKVStoreSync :: list_all_keys ( self . 0 ) ;
636+
637+ async move { res }
638+ }
639+
640+ fn read (
641+ & self , primary_namespace : & str , secondary_namespace : & str , key : & str ,
642+ ) -> impl Future < Output = Result < Vec < u8 > , io:: Error > > + MaybeSend {
643+ let res = KVStoreSync :: read ( self . 0 , primary_namespace, secondary_namespace, key) ;
644+
645+ async move { res }
646+ }
647+
648+ fn write (
649+ & self , primary_namespace : & str , secondary_namespace : & str , key : & str , buf : Vec < u8 > ,
650+ ) -> impl Future < Output = Result < ( ) , io:: Error > > + MaybeSend {
651+ let res = KVStoreSync :: write ( self . 0 , primary_namespace, secondary_namespace, key, buf) ;
652+
653+ async move { res }
654+ }
655+ }
656+
657+ struct MigrationKVStoreAsyncAdapter < ' a , K : ?Sized > ( & ' a K ) ;
658+
659+ impl < K : MigratableKVStore + ?Sized > MigrationKVStore for MigrationKVStoreAsyncAdapter < ' _ , K > {
660+ fn list_all_keys (
661+ & self ,
662+ ) -> impl Future < Output = Result < Vec < MigrationKey > , io:: Error > > + MaybeSend {
663+ MigratableKVStore :: list_all_keys ( self . 0 )
664+ }
665+
666+ fn read (
667+ & self , primary_namespace : & str , secondary_namespace : & str , key : & str ,
668+ ) -> impl Future < Output = Result < Vec < u8 > , io:: Error > > + MaybeSend {
669+ KVStore :: read ( self . 0 , primary_namespace, secondary_namespace, key)
670+ }
671+
672+ fn write (
673+ & self , primary_namespace : & str , secondary_namespace : & str , key : & str , buf : Vec < u8 > ,
674+ ) -> impl Future < Output = Result < ( ) , io:: Error > > + MaybeSend {
675+ KVStore :: write ( self . 0 , primary_namespace, secondary_namespace, key, buf)
676+ }
677+ }
678+
679+ async fn migrate_kv_store_data_inner < S : MigrationKVStore , T : MigrationKVStore > (
680+ source_store : S , target_store : T ,
681+ ) -> Result < ( ) , io:: Error > {
682+ let keys_to_migrate = source_store. list_all_keys ( ) . await ?;
683+
684+ for ( primary_namespace, secondary_namespace, key) in & keys_to_migrate {
685+ let data = source_store. read ( primary_namespace, secondary_namespace, key) . await ?;
686+ target_store. write ( primary_namespace, secondary_namespace, key, data) . await ?;
687+ }
688+
689+ Ok ( ( ) )
690+ }
691+
570692/// Migrates all data from one store to another.
571693///
572694/// This operation assumes that `target_store` is empty, i.e., any data present under copied keys
@@ -578,14 +700,28 @@ pub trait MigratableKVStoreSync: KVStoreSync {
578700pub fn migrate_kv_store_data < S : MigratableKVStoreSync , T : MigratableKVStoreSync > (
579701 source_store : & mut S , target_store : & mut T ,
580702) -> Result < ( ) , io:: Error > {
581- let keys_to_migrate = source_store. list_all_keys ( ) ?;
582-
583- for ( primary_namespace, secondary_namespace, key) in & keys_to_migrate {
584- let data = source_store. read ( primary_namespace, secondary_namespace, key) ?;
585- target_store. write ( primary_namespace, secondary_namespace, key, data) ?;
586- }
703+ poll_sync_future ( migrate_kv_store_data_inner (
704+ MigrationKVStoreSyncAdapter ( source_store) ,
705+ MigrationKVStoreSyncAdapter ( target_store) ,
706+ ) )
707+ }
587708
588- Ok ( ( ) )
709+ /// Migrates all data from one asynchronous store to another.
710+ ///
711+ /// This operation assumes that `target_store` is empty, i.e., any data present under copied keys
712+ /// might get overriden. User must ensure `source_store` is not modified during operation,
713+ /// otherwise no consistency guarantees can be given.
714+ ///
715+ /// Will abort and return an error if any IO operation fails. Note that in this case the
716+ /// `target_store` might get left in an intermediate state.
717+ pub async fn migrate_kv_store_data_async < S : MigratableKVStore , T : MigratableKVStore > (
718+ source_store : & S , target_store : & T ,
719+ ) -> Result < ( ) , io:: Error > {
720+ migrate_kv_store_data_inner (
721+ MigrationKVStoreAsyncAdapter ( source_store) ,
722+ MigrationKVStoreAsyncAdapter ( target_store) ,
723+ )
724+ . await
589725}
590726
591727impl < ChannelSigner : EcdsaChannelSigner , K : KVStoreSync + ?Sized > Persist < ChannelSigner > for K {
0 commit comments