reth_prune/
builder.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use crate::{segments::SegmentSet, Pruner};
use alloy_eips::eip2718::Encodable2718;
use reth_chainspec::MAINNET;
use reth_config::PruneConfig;
use reth_db::{table::Value, transaction::DbTxMut};
use reth_exex_types::FinishedExExHeight;
use reth_primitives_traits::NodePrimitives;
use reth_provider::{
    providers::StaticFileProvider, BlockReader, DBProvider, DatabaseProviderFactory,
    NodePrimitivesProvider, PruneCheckpointWriter, StaticFileProviderFactory,
};
use reth_prune_types::PruneModes;
use std::time::Duration;
use tokio::sync::watch;

/// Contains the information required to build a pruner
#[derive(Debug, Clone)]
pub struct PrunerBuilder {
    /// Minimum pruning interval measured in blocks.
    block_interval: usize,
    /// Pruning configuration for every part of the data that can be pruned.
    segments: PruneModes,
    /// The delete limit for pruner, per run.
    delete_limit: usize,
    /// Time a pruner job can run before timing out.
    timeout: Option<Duration>,
    /// The finished height of all `ExEx`'s.
    finished_exex_height: watch::Receiver<FinishedExExHeight>,
}

impl PrunerBuilder {
    /// Default timeout for a prune run.
    pub const DEFAULT_TIMEOUT: Duration = Duration::from_millis(100);

    /// Creates a new [`PrunerBuilder`] from the given [`PruneConfig`].
    pub fn new(pruner_config: PruneConfig) -> Self {
        Self::default()
            .block_interval(pruner_config.block_interval)
            .segments(pruner_config.segments)
    }

    /// Sets the minimum pruning interval measured in blocks.
    pub const fn block_interval(mut self, block_interval: usize) -> Self {
        self.block_interval = block_interval;
        self
    }

    /// Sets the configuration for every part of the data that can be pruned.
    pub fn segments(mut self, segments: PruneModes) -> Self {
        self.segments = segments;
        self
    }

    /// Sets the delete limit for pruner, per run.
    pub const fn delete_limit(mut self, prune_delete_limit: usize) -> Self {
        self.delete_limit = prune_delete_limit;
        self
    }

    /// Sets the timeout for pruner, per run.
    ///
    /// CAUTION: Account and Storage History prune segments treat this timeout as a soft limit,
    /// meaning they can go beyond it.
    pub const fn timeout(mut self, timeout: Duration) -> Self {
        self.timeout = Some(timeout);
        self
    }

    /// Sets the receiver for the finished height of all `ExEx`'s.
    pub fn finished_exex_height(
        mut self,
        finished_exex_height: watch::Receiver<FinishedExExHeight>,
    ) -> Self {
        self.finished_exex_height = finished_exex_height;
        self
    }

    /// Builds a [Pruner] from the current configuration with the given provider factory.
    pub fn build_with_provider_factory<PF>(self, provider_factory: PF) -> Pruner<PF::ProviderRW, PF>
    where
        PF: DatabaseProviderFactory<
                ProviderRW: PruneCheckpointWriter
                                + BlockReader<Transaction: Encodable2718>
                                + StaticFileProviderFactory<
                    Primitives: NodePrimitives<SignedTx: Value, Receipt: Value>,
                >,
            > + StaticFileProviderFactory<
                Primitives = <PF::ProviderRW as NodePrimitivesProvider>::Primitives,
            >,
    {
        let segments =
            SegmentSet::from_components(provider_factory.static_file_provider(), self.segments);

        Pruner::new_with_factory(
            provider_factory,
            segments.into_vec(),
            self.block_interval,
            self.delete_limit,
            self.timeout,
            self.finished_exex_height,
        )
    }

    /// Builds a [Pruner] from the current configuration with the given static file provider.
    pub fn build<Provider>(
        self,
        static_file_provider: StaticFileProvider<Provider::Primitives>,
    ) -> Pruner<Provider, ()>
    where
        Provider: StaticFileProviderFactory<Primitives: NodePrimitives<SignedTx: Value, Receipt: Value>>
            + DBProvider<Tx: DbTxMut>
            + BlockReader<Transaction: Encodable2718>
            + PruneCheckpointWriter,
    {
        let segments = SegmentSet::<Provider>::from_components(static_file_provider, self.segments);

        Pruner::new(
            segments.into_vec(),
            self.block_interval,
            self.delete_limit,
            self.timeout,
            self.finished_exex_height,
        )
    }
}

impl Default for PrunerBuilder {
    fn default() -> Self {
        Self {
            block_interval: 5,
            segments: PruneModes::none(),
            delete_limit: MAINNET.prune_delete_limit,
            timeout: None,
            finished_exex_height: watch::channel(FinishedExExHeight::NoExExs).1,
        }
    }
}