@@ -54,6 +54,7 @@ use crate::event::EventQueue;
5454use crate :: fee_estimator:: OnchainFeeEstimator ;
5555use crate :: gossip:: GossipSource ;
5656use crate :: io:: sqlite_store:: SqliteStore ;
57+ use crate :: io:: tier_store:: TierStore ;
5758use crate :: io:: utils:: {
5859 read_event_queue, read_external_pathfinding_scores_from_cache, read_network_graph,
5960 read_node_metrics, read_output_sweeper, read_payments, read_peer_info, read_pending_payments,
@@ -151,6 +152,21 @@ impl std::fmt::Debug for LogWriterConfig {
151152 }
152153}
153154
155+ #[ derive( Default ) ]
156+ struct TierStoreConfig {
157+ ephemeral : Option < Arc < DynStore > > ,
158+ backup : Option < Arc < DynStore > > ,
159+ }
160+
161+ impl std:: fmt:: Debug for TierStoreConfig {
162+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
163+ f. debug_struct ( "TierStoreConfig" )
164+ . field ( "ephemeral" , & self . ephemeral . as_ref ( ) . map ( |_| "Arc<DynStore>" ) )
165+ . field ( "backup" , & self . backup . as_ref ( ) . map ( |_| "Arc<DynStore>" ) )
166+ . finish ( )
167+ }
168+ }
169+
154170/// An error encountered during building a [`Node`].
155171///
156172/// [`Node`]: crate::Node
@@ -278,6 +294,7 @@ pub struct NodeBuilder {
278294 liquidity_source_config : Option < LiquiditySourceConfig > ,
279295 log_writer_config : Option < LogWriterConfig > ,
280296 async_payments_role : Option < AsyncPaymentsRole > ,
297+ tier_store_config : Option < TierStoreConfig > ,
281298 runtime_handle : Option < tokio:: runtime:: Handle > ,
282299 pathfinding_scores_sync_config : Option < PathfindingScoresSyncConfig > ,
283300 recovery_mode : bool ,
@@ -296,6 +313,7 @@ impl NodeBuilder {
296313 let gossip_source_config = None ;
297314 let liquidity_source_config = None ;
298315 let log_writer_config = None ;
316+ let tier_store_config = None ;
299317 let runtime_handle = None ;
300318 let pathfinding_scores_sync_config = None ;
301319 let recovery_mode = false ;
@@ -305,6 +323,7 @@ impl NodeBuilder {
305323 gossip_source_config,
306324 liquidity_source_config,
307325 log_writer_config,
326+ tier_store_config,
308327 runtime_handle,
309328 async_payments_role : None ,
310329 pathfinding_scores_sync_config,
@@ -614,6 +633,33 @@ impl NodeBuilder {
614633 self
615634 }
616635
636+ /// Configures the backup store for local disaster recovery.
637+ ///
638+ /// When building with tiered storage, this store receives asynchronous copies
639+ /// of all critical data written to the primary store.
640+ ///
641+ /// Backup writes are non-blocking and do not affect primary store operation performance.
642+ #[ allow( dead_code) ]
643+ pub fn set_backup_store ( & mut self , backup_store : Arc < DynStore > ) -> & mut Self {
644+ let tier_store_config = self . tier_store_config . get_or_insert ( TierStoreConfig :: default ( ) ) ;
645+ tier_store_config. backup = Some ( backup_store) ;
646+ self
647+ }
648+
649+ /// Configures the ephemeral store for non-critical, frequently-accessed data.
650+ ///
651+ /// When building with tiered storage, this store is used for ephemeral data like
652+ /// the network graph and scorer data to reduce latency for reads. Data stored here
653+ /// can be rebuilt if lost.
654+ ///
655+ /// If not set, non-critical data will be stored in the primary store.
656+ #[ allow( dead_code) ]
657+ pub fn set_ephemeral_store ( & mut self , ephemeral_store : Arc < DynStore > ) -> & mut Self {
658+ let tier_store_config = self . tier_store_config . get_or_insert ( TierStoreConfig :: default ( ) ) ;
659+ tier_store_config. ephemeral = Some ( ephemeral_store) ;
660+ self
661+ }
662+
617663 /// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options
618664 /// previously configured.
619665 pub fn build ( & self , node_entropy : NodeEntropy ) -> Result < Node , BuildError > {
@@ -762,6 +808,14 @@ impl NodeBuilder {
762808 }
763809
764810 /// Builds a [`Node`] instance according to the options previously configured.
811+ ///
812+ /// The provided `kv_store` will be used as the primary storage backend. Optionally,
813+ /// an ephemeral store for frequently-accessed non-critical data (e.g., network graph, scorer)
814+ /// and a backup store for local disaster recovery can be configured via
815+ /// [`set_ephemeral_store`] and [`set_backup_store`].
816+ ///
817+ /// [`set_ephemeral_store`]: Self::set_ephemeral_store
818+ /// [`set_backup_store`]: Self::set_backup_store
765819 pub fn build_with_store < S : SyncAndAsyncKVStore + Send + Sync + ' static > (
766820 & self , node_entropy : NodeEntropy , kv_store : S ,
767821 ) -> Result < Node , BuildError > {
@@ -776,6 +830,15 @@ impl NodeBuilder {
776830 } ) ?)
777831 } ;
778832
833+ let ts_config = self . tier_store_config . as_ref ( ) ;
834+ let primary_store: Arc < DynStore > = Arc :: new ( DynStoreWrapper ( kv_store) ) ;
835+ let mut tier_store =
836+ TierStore :: new ( primary_store, Arc :: clone ( & runtime) , Arc :: clone ( & logger) ) ;
837+ if let Some ( config) = ts_config {
838+ config. ephemeral . as_ref ( ) . map ( |s| tier_store. set_ephemeral_store ( Arc :: clone ( s) ) ) ;
839+ config. backup . as_ref ( ) . map ( |s| tier_store. set_backup_store ( Arc :: clone ( s) ) ) ;
840+ }
841+
779842 let seed_bytes = node_entropy. to_seed_bytes ( ) ;
780843 let config = Arc :: new ( self . config . clone ( ) ) ;
781844
@@ -790,7 +853,7 @@ impl NodeBuilder {
790853 seed_bytes,
791854 runtime,
792855 logger,
793- Arc :: new ( DynStoreWrapper ( kv_store ) ) ,
856+ Arc :: new ( DynStoreWrapper ( tier_store ) ) ,
794857 )
795858 }
796859}
0 commit comments