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