1use crate::{segments::SegmentSet, Pruner};
2use reth_config::PruneConfig;
3use reth_db_api::{table::Value, transaction::DbTxMut};
4use reth_exex_types::FinishedExExHeight;
5use reth_primitives_traits::NodePrimitives;
6use reth_provider::{
7 providers::StaticFileProvider, BlockReader, ChainStateBlockReader, DBProvider,
8 DatabaseProviderFactory, NodePrimitivesProvider, PruneCheckpointReader, PruneCheckpointWriter,
9 RocksDBProviderFactory, StageCheckpointReader, StaticFileProviderFactory,
10};
11use reth_prune_types::PruneModes;
12use reth_storage_api::{ChangeSetReader, StorageChangeSetReader, StorageSettingsCache};
13use std::time::Duration;
14use tokio::sync::watch;
15
16#[derive(Debug, Clone)]
18pub struct PrunerBuilder {
19 block_interval: usize,
21 segments: PruneModes,
23 delete_limit: usize,
25 timeout: Option<Duration>,
27 minimum_pruning_distance: Option<u64>,
29 finished_exex_height: watch::Receiver<FinishedExExHeight>,
31}
32
33impl PrunerBuilder {
34 pub fn new(pruner_config: PruneConfig) -> Self {
36 let min_distance = pruner_config.minimum_pruning_distance;
37 let mut builder = Self::default()
38 .block_interval(pruner_config.block_interval)
39 .segments(pruner_config.segments);
40 if min_distance != reth_prune_types::MINIMUM_UNWIND_SAFE_DISTANCE {
41 builder.minimum_pruning_distance = Some(min_distance);
42 }
43 builder
44 }
45
46 pub const fn block_interval(mut self, block_interval: usize) -> Self {
48 self.block_interval = block_interval;
49 self
50 }
51
52 pub fn segments(mut self, segments: PruneModes) -> Self {
54 self.segments = segments;
55 self
56 }
57
58 pub const fn delete_limit(mut self, prune_delete_limit: usize) -> Self {
60 self.delete_limit = prune_delete_limit;
61 self
62 }
63
64 pub const fn timeout(mut self, timeout: Duration) -> Self {
69 self.timeout = Some(timeout);
70 self
71 }
72
73 pub fn finished_exex_height(
75 mut self,
76 finished_exex_height: watch::Receiver<FinishedExExHeight>,
77 ) -> Self {
78 self.finished_exex_height = finished_exex_height;
79 self
80 }
81
82 pub fn build_with_provider_factory<PF>(self, provider_factory: PF) -> Pruner<PF::ProviderRW, PF>
84 where
85 PF: DatabaseProviderFactory<
86 ProviderRW: PruneCheckpointWriter
87 + PruneCheckpointReader
88 + BlockReader
89 + ChainStateBlockReader
90 + StorageSettingsCache
91 + StageCheckpointReader
92 + ChangeSetReader
93 + StorageChangeSetReader
94 + RocksDBProviderFactory
95 + StaticFileProviderFactory<
96 Primitives: NodePrimitives<SignedTx: Value, Receipt: Value, BlockHeader: Value>,
97 >,
98 > + StaticFileProviderFactory<
99 Primitives = <PF::ProviderRW as NodePrimitivesProvider>::Primitives,
100 >,
101 {
102 let segments =
103 SegmentSet::from_components(provider_factory.static_file_provider(), self.segments);
104
105 let mut pruner = Pruner::new_with_factory(
106 provider_factory,
107 segments.into_vec(),
108 self.block_interval,
109 self.delete_limit,
110 self.timeout,
111 self.finished_exex_height,
112 );
113 if let Some(distance) = self.minimum_pruning_distance {
114 pruner = pruner.with_minimum_pruning_distance(distance);
115 }
116 pruner
117 }
118
119 pub fn build<Provider>(
121 self,
122 static_file_provider: StaticFileProvider<Provider::Primitives>,
123 ) -> Pruner<Provider, ()>
124 where
125 Provider: StaticFileProviderFactory<
126 Primitives: NodePrimitives<SignedTx: Value, Receipt: Value, BlockHeader: Value>,
127 > + DBProvider<Tx: DbTxMut>
128 + BlockReader
129 + ChainStateBlockReader
130 + PruneCheckpointWriter
131 + PruneCheckpointReader
132 + StorageSettingsCache
133 + StageCheckpointReader
134 + ChangeSetReader
135 + StorageChangeSetReader
136 + RocksDBProviderFactory,
137 {
138 let segments = SegmentSet::<Provider>::from_components(static_file_provider, self.segments);
139
140 let mut pruner = Pruner::new(
141 segments.into_vec(),
142 self.block_interval,
143 self.delete_limit,
144 self.timeout,
145 self.finished_exex_height,
146 );
147 if let Some(distance) = self.minimum_pruning_distance {
148 pruner = pruner.with_minimum_pruning_distance(distance);
149 }
150 pruner
151 }
152}
153
154impl Default for PrunerBuilder {
155 fn default() -> Self {
156 Self {
157 block_interval: 5,
158 segments: PruneModes::default(),
159 delete_limit: usize::MAX,
160 timeout: None,
161 minimum_pruning_distance: None,
162 finished_exex_height: watch::channel(FinishedExExHeight::NoExExs).1,
163 }
164 }
165}