reth_prune/
builder.rs

1use crate::{segments::SegmentSet, Pruner};
2use alloy_eips::eip2718::Encodable2718;
3use reth_chainspec::MAINNET_PRUNE_DELETE_LIMIT;
4use reth_config::PruneConfig;
5use reth_db_api::{table::Value, transaction::DbTxMut};
6use reth_exex_types::FinishedExExHeight;
7use reth_primitives_traits::NodePrimitives;
8use reth_provider::{
9    providers::StaticFileProvider, BlockReader, DBProvider, DatabaseProviderFactory,
10    NodePrimitivesProvider, PruneCheckpointReader, PruneCheckpointWriter,
11    StaticFileProviderFactory,
12};
13use reth_prune_types::PruneModes;
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    /// Default timeout for a prune run.
34    pub const DEFAULT_TIMEOUT: Duration = Duration::from_millis(100);
35
36    /// Creates a new [`PrunerBuilder`] from the given [`PruneConfig`].
37    pub fn new(pruner_config: PruneConfig) -> Self {
38        Self::default()
39            .block_interval(pruner_config.block_interval)
40            .segments(pruner_config.segments)
41    }
42
43    /// Sets the minimum pruning interval measured in blocks.
44    pub const fn block_interval(mut self, block_interval: usize) -> Self {
45        self.block_interval = block_interval;
46        self
47    }
48
49    /// Sets the configuration for every part of the data that can be pruned.
50    pub fn segments(mut self, segments: PruneModes) -> Self {
51        self.segments = segments;
52        self
53    }
54
55    /// Sets the delete limit for pruner, per run.
56    pub const fn delete_limit(mut self, prune_delete_limit: usize) -> Self {
57        self.delete_limit = prune_delete_limit;
58        self
59    }
60
61    /// Sets the timeout for pruner, per run.
62    ///
63    /// CAUTION: Account and Storage History prune segments treat this timeout as a soft limit,
64    /// meaning they can go beyond it.
65    pub const fn timeout(mut self, timeout: Duration) -> Self {
66        self.timeout = Some(timeout);
67        self
68    }
69
70    /// Sets the receiver for the finished height of all `ExEx`'s.
71    pub fn finished_exex_height(
72        mut self,
73        finished_exex_height: watch::Receiver<FinishedExExHeight>,
74    ) -> Self {
75        self.finished_exex_height = finished_exex_height;
76        self
77    }
78
79    /// Builds a [Pruner] from the current configuration with the given provider factory.
80    pub fn build_with_provider_factory<PF>(self, provider_factory: PF) -> Pruner<PF::ProviderRW, PF>
81    where
82        PF: DatabaseProviderFactory<
83                ProviderRW: PruneCheckpointWriter
84                                + PruneCheckpointReader
85                                + BlockReader<Transaction: Encodable2718>
86                                + StaticFileProviderFactory<
87                    Primitives: NodePrimitives<SignedTx: Value, Receipt: Value, BlockHeader: Value>,
88                >,
89            > + StaticFileProviderFactory<
90                Primitives = <PF::ProviderRW as NodePrimitivesProvider>::Primitives,
91            >,
92    {
93        let segments =
94            SegmentSet::from_components(provider_factory.static_file_provider(), self.segments);
95
96        Pruner::new_with_factory(
97            provider_factory,
98            segments.into_vec(),
99            self.block_interval,
100            self.delete_limit,
101            self.timeout,
102            self.finished_exex_height,
103        )
104    }
105
106    /// Builds a [Pruner] from the current configuration with the given static file provider.
107    pub fn build<Provider>(
108        self,
109        static_file_provider: StaticFileProvider<Provider::Primitives>,
110    ) -> Pruner<Provider, ()>
111    where
112        Provider: StaticFileProviderFactory<
113                Primitives: NodePrimitives<SignedTx: Value, Receipt: Value, BlockHeader: Value>,
114            > + DBProvider<Tx: DbTxMut>
115            + BlockReader<Transaction: Encodable2718>
116            + PruneCheckpointWriter
117            + PruneCheckpointReader,
118    {
119        let segments = SegmentSet::<Provider>::from_components(static_file_provider, self.segments);
120
121        Pruner::new(
122            segments.into_vec(),
123            self.block_interval,
124            self.delete_limit,
125            self.timeout,
126            self.finished_exex_height,
127        )
128    }
129}
130
131impl Default for PrunerBuilder {
132    fn default() -> Self {
133        Self {
134            block_interval: 5,
135            segments: PruneModes::none(),
136            delete_limit: MAINNET_PRUNE_DELETE_LIMIT,
137            timeout: None,
138            finished_exex_height: watch::channel(FinishedExExHeight::NoExExs).1,
139        }
140    }
141}