@@ -69,6 +69,8 @@ use crate::data_store::{KeepAllEntries, KeepLeastRecentlyUsed};
6969use crate :: entropy:: NodeEntropy ;
7070use crate :: event:: EventQueue ;
7171use crate :: fee_estimator:: OnchainFeeEstimator ;
72+ #[ cfg( all( feature = "uniffi" , feature = "storage-tier" ) ) ]
73+ use crate :: ffi:: DynStoreTrait ;
7274use crate :: gossip:: GossipSource ;
7375#[ cfg( feature = "storage-filesystem" ) ]
7476use crate :: io:: fs_store:: open_or_migrate_fs_store;
@@ -716,7 +718,7 @@ impl NodeBuilder {
716718 /// If not set, durable data will be stored only in the primary store.
717719 ///
718720 /// [`SQLITE_BACKUP_DB_FILE_NAME`]: crate::io::sqlite_store::SQLITE_BACKUP_DB_FILE_NAME
719- #[ cfg( all ( not ( feature = "uniffi" ) , feature = " storage-tier") ) ]
721+ #[ cfg( feature = "storage-tier" ) ]
720722 pub fn set_backup_storage_dir_path ( & mut self , backup_storage_dir_path : String ) -> & mut Self {
721723 let tier_store_config = self . tier_store_config . get_or_insert ( TierStoreConfig :: default ( ) ) ;
722724 tier_store_config. backup_storage_dir_path = Some ( backup_storage_dir_path. into ( ) ) ;
@@ -729,7 +731,7 @@ impl NodeBuilder {
729731 /// the network graph and scorer. Data stored here can be rebuilt if lost.
730732 ///
731733 /// If not set, non-critical data will be stored in the primary store.
732- #[ cfg( all ( not ( feature = "uniffi" ) , feature = " storage-tier") ) ]
734+ #[ cfg( feature = "storage-tier" ) ]
733735 pub fn set_ephemeral_storage_dir_path (
734736 & mut self , ephemeral_storage_dir_path : String ,
735737 ) -> & mut Self {
@@ -962,6 +964,7 @@ impl NodeBuilder {
962964 /// [`set_ephemeral_storage_dir_path`]: Self::set_ephemeral_storage_dir_path
963965 /// [`set_backup_storage_dir_path`]: Self::set_backup_storage_dir_path
964966 #[ cfg( not( feature = "storage-tier" ) ) ]
967+ #[ cfg_attr( feature = "uniffi" , allow( dead_code) ) ]
965968 pub fn build_with_store < S : PaginatedKVStore + Send + Sync + ' static > (
966969 & self , node_entropy : NodeEntropy , kv_store : S ,
967970 ) -> Result < Node , BuildError > {
@@ -982,6 +985,7 @@ impl NodeBuilder {
982985 /// [`set_ephemeral_storage_dir_path`]: Self::set_ephemeral_storage_dir_path
983986 /// [`set_backup_storage_dir_path`]: Self::set_backup_storage_dir_path
984987 #[ cfg( feature = "storage-tier" ) ]
988+ #[ cfg_attr( feature = "uniffi" , allow( dead_code) ) ]
985989 pub fn build_with_store < S : PaginatedKVStore + MigratableKVStore + Send + Sync + ' static > (
986990 & self , node_entropy : NodeEntropy , kv_store : S ,
987991 ) -> Result < Node , BuildError > {
@@ -1032,9 +1036,28 @@ impl NodeBuilder {
10321036 > (
10331037 & self , node_entropy : NodeEntropy , kv_store : S , runtime : Arc < Runtime > , logger : Arc < Logger > ,
10341038 ) -> Result < Node , BuildError > {
1039+ let primary_store: Arc < DynStore > = Arc :: new ( DynStoreWrapper ( kv_store) ) ;
1040+ let store = self . setup_tier_store ( primary_store, & runtime, & logger) ?;
1041+ self . build_with_dyn_store ( node_entropy, store, runtime, logger)
1042+ }
1043+
1044+ #[ cfg( all( feature = "uniffi" , feature = "storage-tier" ) ) ]
1045+ fn build_with_ffi_store (
1046+ & self , node_entropy : NodeEntropy , kv_store : Arc < dyn DynStoreTrait > ,
1047+ ) -> Result < Node , BuildError > {
1048+ let logger = setup_logger ( & self . log_writer_config , & self . config ) ?;
1049+ let runtime = self . setup_runtime ( & logger) ?;
1050+ let primary_store: Arc < DynStore > = Arc :: new ( crate :: ffi:: DynStore :: new ( kv_store) ) ;
1051+ let store = self . setup_tier_store ( primary_store, & runtime, & logger) ?;
1052+ self . build_with_dyn_store ( node_entropy, store, runtime, logger)
1053+ }
1054+
1055+ #[ cfg( feature = "storage-tier" ) ]
1056+ fn setup_tier_store (
1057+ & self , primary_store : Arc < DynStore > , runtime : & Arc < Runtime > , logger : & Arc < Logger > ,
1058+ ) -> Result < Arc < DynStore > , BuildError > {
10351059 let store: Arc < DynStore > = {
10361060 let ts_config = self . tier_store_config . as_ref ( ) ;
1037- let primary_store = Arc :: new ( DynStoreWrapper ( kv_store) ) ;
10381061 let mut tier_store = TierStore :: new ( primary_store, Arc :: clone ( & logger) ) ;
10391062 let tier_index_exists = PathBuf :: from ( & self . config . storage_dir_path )
10401063 . join ( io:: sqlite_store:: SQLITE_TIER_INDEX_DB_FILE_NAME )
@@ -1098,7 +1121,7 @@ impl NodeBuilder {
10981121 } ) ?;
10991122 Arc :: new ( DynStoreWrapper ( tier_store) )
11001123 } ;
1101- self . build_with_dyn_store ( node_entropy , store, runtime , logger )
1124+ Ok ( store)
11021125 }
11031126
11041127 fn build_with_dyn_store (
@@ -1645,23 +1668,45 @@ impl Builder {
16451668 }
16461669}
16471670
1648- #[ cfg( feature = "uniffi" ) ]
1671+ #[ cfg( all ( feature = "uniffi" , not ( feature = "storage-tier" ) ) ) ]
16491672impl ArcedNodeBuilder {
16501673 /// Builds a [`Node`] instance according to the options previously configured.
1651- // Note that the generics here don't actually work for Uniffi, but we don't currently expose
1652- // this so its not needed.
1653- #[ cfg( not( feature = "storage-tier" ) ) ]
1674+ // Note that the generics here don't actually work for UniFFI, but we don't currently expose
1675+ // this so it is only used by Rust tests compiled with the `uniffi` feature.
16541676 pub fn build_with_store < S : PaginatedKVStore + Send + Sync + ' static > (
16551677 & self , node_entropy : Arc < NodeEntropy > , kv_store : S ,
16561678 ) -> Result < Arc < Node > , BuildError > {
16571679 self . inner . read ( ) . expect ( "lock" ) . build_with_store ( * node_entropy, kv_store) . map ( Arc :: new)
16581680 }
1681+ }
16591682
1660- #[ cfg( feature = "storage-tier" ) ]
1661- pub fn build_with_store < S : PaginatedKVStore + MigratableKVStore + Send + Sync + ' static > (
1662- & self , node_entropy : Arc < NodeEntropy > , kv_store : S ,
1683+ #[ cfg( all( feature = "uniffi" , feature = "storage-tier" ) ) ]
1684+ #[ uniffi:: export]
1685+ impl Builder {
1686+ /// Configures a local SQLite backup store for durable data.
1687+ ///
1688+ /// The backup is brought up to date before node construction completes. While configured,
1689+ /// durable writes and removals only succeed when both primary and backup storage succeed.
1690+ pub fn set_backup_storage_dir_path ( & self , backup_storage_dir_path : String ) {
1691+ self . inner . write ( ) . expect ( "lock" ) . set_backup_storage_dir_path ( backup_storage_dir_path) ;
1692+ }
1693+
1694+ /// Configures a local SQLite store for rebuildable cache data.
1695+ pub fn set_ephemeral_storage_dir_path ( & self , ephemeral_storage_dir_path : String ) {
1696+ self . inner
1697+ . write ( )
1698+ . expect ( "lock" )
1699+ . set_ephemeral_storage_dir_path ( ephemeral_storage_dir_path) ;
1700+ }
1701+
1702+ /// Builds a [`Node`] instance according to the options previously configured.
1703+ ///
1704+ /// The provided store is used as authoritative primary storage. It must support paginated
1705+ /// namespace listing and exhaustive key enumeration for backup synchronization.
1706+ pub fn build_with_store (
1707+ & self , node_entropy : Arc < NodeEntropy > , kv_store : Arc < dyn DynStoreTrait > ,
16631708 ) -> Result < Arc < Node > , BuildError > {
1664- self . inner . read ( ) . expect ( "lock" ) . build_with_store ( * node_entropy, kv_store) . map ( Arc :: new)
1709+ self . inner . read ( ) . expect ( "lock" ) . build_with_ffi_store ( * node_entropy, kv_store) . map ( Arc :: new)
16651710 }
16661711}
16671712
0 commit comments