Skip to main content

reth_prune/
builder.rs

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/// Contains the information required to build a pruner
18#[derive(Debug, Clone)]
19pub struct PrunerBuilder {
20    /// Minimum pruning interval measured in blocks.
21    block_interval: usize,
22    /// Pruning configuration for every part of the data that can be pruned.
23    segments: PruneModes,
24    /// The delete limit for pruner, per run.
25    delete_limit: usize,
26    /// Time a pruner job can run before timing out.
27    timeout: Option<Duration>,
28    /// The finished height of all `ExEx`'s.
29    finished_exex_height: watch::Receiver<FinishedExExHeight>,
30}
31
32impl PrunerBuilder {
33    /// Creates a new [`PrunerBuilder`] from the given [`PruneConfig`].
34    pub fn new(pruner_config: PruneConfig) -> Self {
35        Self::default()
36            .block_interval(pruner_config.block_interval)
37            .segments(pruner_config.segments)
38    }
39
40    /// Sets the minimum pruning interval measured in blocks.
41    pub const fn block_interval(mut self, block_interval: usize) -> Self {
42        self.block_interval = block_interval;
43        self
44    }
45
46    /// Sets the configuration for every part of the data that can be pruned.
47    pub fn segments(mut self, segments: PruneModes) -> Self {
48        self.segments = segments;
49        self
50    }
51
52    /// Sets the delete limit for pruner, per run.
53    pub const fn delete_limit(mut self, prune_delete_limit: usize) -> Self {
54        self.delete_limit = prune_delete_limit;
55        self
56    }
57
58    /// Sets the timeout for pruner, per run.
59    ///
60    /// CAUTION: Account and Storage History prune segments treat this timeout as a soft limit,
61    /// meaning they can go beyond it.
62    pub const fn timeout(mut self, timeout: Duration) -> Self {
63        self.timeout = Some(timeout);
64        self
65    }
66
67    /// Sets the receiver for the finished height of all `ExEx`'s.
68    pub fn finished_exex_height(
69        mut self,
70        finished_exex_height: watch::Receiver<FinishedExExHeight>,
71    ) -> Self {
72        self.finished_exex_height = finished_exex_height;
73        self
74    }
75
76    /// Builds a [Pruner] from the current configuration with the given provider factory.
77    pub fn build_with_provider_factory<PF>(self, provider_factory: PF) -> Pruner<PF::ProviderRW, PF>
78    where
79        PF: DatabaseProviderFactory<
80                ProviderRW: PruneCheckpointWriter
81                                + PruneCheckpointReader
82                                + BlockReader<Transaction: Encodable2718>
83                                + ChainStateBlockReader
84                                + StorageSettingsCache
85                                + StageCheckpointReader
86                                + ChangeSetReader
87                                + StorageChangeSetReader
88                                + RocksDBProviderFactory
89                                + StaticFileProviderFactory<
90                    Primitives: NodePrimitives<SignedTx: Value, Receipt: Value, BlockHeader: Value>,
91                >,
92            > + StaticFileProviderFactory<
93                Primitives = <PF::ProviderRW as NodePrimitivesProvider>::Primitives,
94            >,
95    {
96        let segments =
97            SegmentSet::from_components(provider_factory.static_file_provider(), self.segments);
98
99        Pruner::new_with_factory(
100            provider_factory,
101            segments.into_vec(),
102            self.block_interval,
103            self.delete_limit,
104            self.timeout,
105            self.finished_exex_height,
106        )
107    }
108
109    /// Builds a [Pruner] from the current configuration with the given static file provider.
110    pub fn build<Provider>(
111        self,
112        static_file_provider: StaticFileProvider<Provider::Primitives>,
113    ) -> Pruner<Provider, ()>
114    where
115        Provider: StaticFileProviderFactory<
116                Primitives: NodePrimitives<SignedTx: Value, Receipt: Value, BlockHeader: Value>,
117            > + DBProvider<Tx: DbTxMut>
118            + BlockReader<Transaction: Encodable2718>
119            + ChainStateBlockReader
120            + PruneCheckpointWriter
121            + PruneCheckpointReader
122            + StorageSettingsCache
123            + StageCheckpointReader
124            + ChangeSetReader
125            + StorageChangeSetReader
126            + RocksDBProviderFactory,
127    {
128        let segments = SegmentSet::<Provider>::from_components(static_file_provider, self.segments);
129
130        Pruner::new(
131            segments.into_vec(),
132            self.block_interval,
133            self.delete_limit,
134            self.timeout,
135            self.finished_exex_height,
136        )
137    }
138}
139
140impl Default for PrunerBuilder {
141    fn default() -> Self {
142        Self {
143            block_interval: 5,
144            segments: PruneModes::default(),
145            delete_limit: usize::MAX,
146            timeout: None,
147            finished_exex_height: watch::channel(FinishedExExHeight::NoExExs).1,
148        }
149    }
150}