hotshot_query_service/data_source/storage/
pruning.rs1use std::{fmt::Debug, time::Duration};
14
15use anyhow::bail;
16use async_trait::async_trait;
17
18#[derive(Clone, Debug)]
19pub struct PrunerCfg {
20 pruning_threshold: Option<u64>,
21 minimum_retention: Duration,
22 target_retention: Duration,
23 batch_size: u64,
24 max_usage: u16,
25 interval: Duration,
26 incremental_vacuum_pages: u64,
27 state_tables: Vec<String>,
28}
29
30#[async_trait]
31pub trait PruneStorage: PrunerConfig {
32 type Pruner: Default + Send;
33
34 async fn get_disk_usage(&self) -> anyhow::Result<u64> {
35 Ok(0)
36 }
37
38 async fn prune(&self, _pruner: &mut Self::Pruner) -> anyhow::Result<Option<u64>> {
39 Ok(None)
40 }
41
42 async fn vacuum(&self) -> anyhow::Result<()> {
43 Ok(())
44 }
45}
46
47#[async_trait]
48pub trait PrunedHeightStorage: Sized {
49 async fn load_pruned_height(&mut self) -> anyhow::Result<Option<u64>> {
50 Ok(None)
51 }
52}
53
54#[async_trait]
55pub trait PrunedHeightDataSource: Sized {
56 async fn load_pruned_height(&self) -> anyhow::Result<Option<u64>> {
57 Ok(None)
58 }
59}
60
61pub trait PrunerConfig {
62 fn set_pruning_config(&mut self, _cfg: PrunerCfg) {}
63 fn get_pruning_config(&self) -> Option<PrunerCfg> {
64 None
65 }
66}
67
68impl PrunerCfg {
69 pub fn new() -> Self {
70 Default::default()
71 }
72
73 pub fn validate(&self) -> anyhow::Result<()> {
74 if let Some(pruning_threshold) = self.pruning_threshold {
75 if pruning_threshold == 0 {
76 bail!("pruning_threshold must be greater than 0 or set to None")
77 }
78 }
79
80 if self.max_usage > 10000 {
81 bail!("max_usage must be less than or equal to 10000")
82 }
83
84 Ok(())
85 }
86
87 pub fn with_state_tables(mut self, state_tables: Vec<String>) -> Self {
88 self.state_tables = state_tables;
89 self
90 }
91
92 pub fn with_pruning_threshold(mut self, pruning_threshold: u64) -> Self {
93 self.pruning_threshold = Some(pruning_threshold);
94 self
95 }
96
97 pub fn with_minimum_retention(mut self, minimum_retention: Duration) -> Self {
98 self.minimum_retention = minimum_retention;
99 self
100 }
101
102 pub fn with_target_retention(mut self, target_retention: Duration) -> Self {
103 self.target_retention = target_retention;
104 self
105 }
106
107 pub fn with_batch_size(mut self, batch_size: u64) -> Self {
108 self.batch_size = batch_size;
109 self
110 }
111
112 pub fn with_max_usage(mut self, max_usage: u16) -> Self {
113 self.max_usage = max_usage;
114 self
115 }
116
117 pub fn with_interval(mut self, interval: Duration) -> Self {
118 self.interval = interval;
119 self
120 }
121
122 pub fn with_incremental_vacuum_pages(mut self, pages: u64) -> Self {
123 self.incremental_vacuum_pages = pages;
124 self
125 }
126
127 pub fn pruning_threshold(&self) -> Option<u64> {
133 self.pruning_threshold
134 }
135
136 pub fn minimum_retention(&self) -> Duration {
140 self.minimum_retention
141 }
142
143 pub fn target_retention(&self) -> Duration {
148 self.target_retention
149 }
150
151 pub fn batch_size(&self) -> u64 {
153 self.batch_size
154 }
155
156 pub fn max_usage(&self) -> u16 {
162 self.max_usage
163 }
164
165 pub fn interval(&self) -> Duration {
167 self.interval
168 }
169
170 pub fn incremental_vacuum_pages(&self) -> u64 {
172 self.incremental_vacuum_pages
173 }
174
175 pub fn state_tables(&self) -> Vec<String> {
177 self.state_tables.clone()
178 }
179}
180
181impl Default for PrunerCfg {
182 fn default() -> Self {
183 Self {
184 pruning_threshold: Some(3 * 10_u64.pow(12)),
186 minimum_retention: Duration::from_secs(24 * 3600),
188 target_retention: Duration::from_secs(7 * 24 * 3600),
190 batch_size: 30000,
191 max_usage: 8000,
193 interval: Duration::from_secs(5400),
195 incremental_vacuum_pages: 8000,
197 state_tables: Vec::new(),
198 }
199 }
200}