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