feoxdb/core/store/builder.rs
1use std::time::Duration;
2
3use crate::constants::*;
4use crate::core::ttl_sweep::TtlConfig;
5use crate::error::Result;
6
7use super::FeoxStore;
8
9/// Configuration options for FeoxStore.
10///
11/// Use `StoreBuilder` for a more ergonomic way to configure the store.
12pub struct StoreConfig {
13 pub hash_bits: u32,
14 pub memory_only: bool,
15 pub enable_caching: bool,
16 pub device_path: Option<String>,
17 pub file_size: Option<u64>,
18 pub max_memory: Option<usize>,
19 pub enable_ttl: bool,
20 pub ttl_config: Option<TtlConfig>,
21}
22
23/// Builder for creating FeoxStore with custom configuration.
24///
25/// Provides a fluent interface for configuring store parameters.
26///
27/// # Example
28///
29/// ```rust
30/// use feoxdb::FeoxStore;
31///
32/// # fn main() -> feoxdb::Result<()> {
33/// let store = FeoxStore::builder()
34/// .max_memory(1_000_000_000)
35/// .hash_bits(20)
36/// .enable_ttl(true)
37/// .build()?;
38/// # Ok(())
39/// # }
40/// ```
41pub struct StoreBuilder {
42 hash_bits: u32,
43 device_path: Option<String>,
44 file_size: Option<u64>,
45 max_memory: Option<usize>,
46 enable_caching: Option<bool>,
47 enable_ttl: bool,
48 ttl_config: Option<TtlConfig>,
49}
50
51impl StoreBuilder {
52 pub fn new() -> Self {
53 Self {
54 hash_bits: DEFAULT_HASH_BITS,
55 device_path: None,
56 file_size: None,
57 max_memory: Some(DEFAULT_MAX_MEMORY),
58 enable_caching: None, // Disable caching for memory-only mode
59 enable_ttl: false,
60 ttl_config: None,
61 }
62 }
63
64 /// Set the device path for persistent storage.
65 ///
66 /// When set, data will be persisted to disk asynchronously.
67 /// If not set, the store operates in memory-only mode.
68 pub fn device_path(mut self, path: impl Into<String>) -> Self {
69 self.device_path = Some(path.into());
70 self
71 }
72
73 /// Set the initial file size for new persistent stores (in bytes).
74 ///
75 /// When creating a new persistent store file, it will be pre-allocated
76 /// to this size for better performance. If not set, defaults to 1GB.
77 /// This option is ignored for existing files.
78 ///
79 /// # Example
80 ///
81 /// ```no_run
82 /// use feoxdb::FeoxStore;
83 ///
84 /// # fn main() -> feoxdb::Result<()> {
85 /// let store = FeoxStore::builder()
86 /// .device_path("/path/to/data.feox")
87 /// .file_size(10 * 1024 * 1024 * 1024) // 10GB
88 /// .build()?;
89 /// # Ok(())
90 /// # }
91 /// ```
92 pub fn file_size(mut self, size: u64) -> Self {
93 self.file_size = Some(size);
94 self
95 }
96
97 /// Set the maximum memory limit (in bytes).
98 ///
99 /// The store will start evicting entries when this limit is approached.
100 /// Default: 1GB
101 pub fn max_memory(mut self, limit: usize) -> Self {
102 self.max_memory = Some(limit);
103 self
104 }
105
106 /// Remove memory limit.
107 ///
108 /// Use with caution as the store can grow unbounded.
109 pub fn no_memory_limit(mut self) -> Self {
110 self.max_memory = None;
111 self
112 }
113
114 /// Set number of hash bits (determines hash table size).
115 ///
116 /// More bits = larger hash table = better performance for large datasets.
117 /// Default: 18 (256K buckets)
118 pub fn hash_bits(mut self, bits: u32) -> Self {
119 self.hash_bits = bits;
120 self
121 }
122
123 /// Enable or disable caching.
124 ///
125 /// When enabled, frequently accessed values are kept in memory
126 /// even after being written to disk. Uses CLOCK eviction algorithm.
127 pub fn enable_caching(mut self, enable: bool) -> Self {
128 self.enable_caching = Some(enable);
129 self
130 }
131
132 /// Enable or disable TTL (Time-To-Live) functionality.
133 ///
134 /// When disabled (default), TTL operations will return errors and no background cleaner runs.
135 /// When enabled, keys can have expiry times and a background cleaner removes expired keys.
136 /// Default: false (disabled for optimal performance)
137 pub fn enable_ttl(mut self, enable: bool) -> Self {
138 self.enable_ttl = enable;
139 if enable {
140 let mut config = self.ttl_config.unwrap_or_default();
141 config.enabled = true;
142 self.ttl_config = Some(config);
143 }
144 self
145 }
146
147 /// Enable or disable TTL sweeper.
148 ///
149 /// When enabled, a background thread periodically removes expired keys.
150 /// Note: This method is deprecated in favor of enable_ttl().
151 pub fn enable_ttl_cleaner(mut self, enable: bool) -> Self {
152 let mut config = self.ttl_config.unwrap_or_default();
153 config.enabled = enable;
154 self.ttl_config = Some(config);
155 self.enable_ttl = enable; // Also enable TTL when cleaner is enabled
156 self
157 }
158
159 /// Configure TTL sweeper with custom parameters.
160 ///
161 /// # Arguments
162 ///
163 /// * `sample_size` - Keys to check per batch
164 /// * `threshold` - Continue if >threshold expired (0.0-1.0)
165 /// * `max_time_ms` - Max milliseconds per cleaning run
166 /// * `interval_ms` - Sleep between runs
167 pub fn ttl_sweeper_config(
168 mut self,
169 sample_size: usize,
170 threshold: f32,
171 max_time_ms: u64,
172 interval_ms: u64,
173 ) -> Self {
174 self.ttl_config = Some(TtlConfig {
175 sample_size,
176 expiry_threshold: threshold,
177 max_iterations: 16,
178 max_time_per_run: Duration::from_millis(max_time_ms),
179 sleep_interval: Duration::from_millis(interval_ms),
180 enabled: true,
181 });
182 self
183 }
184
185 /// Build the FeoxStore
186 pub fn build(self) -> Result<FeoxStore> {
187 let memory_only = self.device_path.is_none();
188 let enable_caching = self.enable_caching.unwrap_or(!memory_only);
189
190 let config = StoreConfig {
191 hash_bits: self.hash_bits,
192 memory_only,
193 enable_caching,
194 device_path: self.device_path,
195 file_size: self.file_size,
196 max_memory: self.max_memory,
197 enable_ttl: self.enable_ttl,
198 ttl_config: self.ttl_config,
199 };
200
201 FeoxStore::with_config(config)
202 }
203}
204
205impl Default for StoreBuilder {
206 fn default() -> Self {
207 Self::new()
208 }
209}