Skip to main content

engram/
config.rs

1use std::{
2    path::{Path, PathBuf},
3    time::Duration,
4};
5
6/// The encoding used for values written to persistent storage.
7#[derive(Clone, Debug, Eq, PartialEq)]
8pub enum Compression {
9    /// Store serialized bytes as-is.
10    Disabled,
11    /// Store serialized bytes compressed with Zstandard at the supplied level.
12    Zstd { level: i32 },
13}
14
15impl Default for Compression {
16    fn default() -> Self {
17        Self::Zstd { level: 3 }
18    }
19}
20
21/// SQLite's durability/performance trade-off in WAL mode.
22#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
23pub enum SqliteSynchronous {
24    /// Request the strongest SQLite durability setting.
25    #[default]
26    Full,
27    /// Usually faster, but the last committed transactions can be lost after an OS
28    /// crash or power failure. SQLite remains internally consistent.
29    Normal,
30}
31
32impl SqliteSynchronous {
33    pub(crate) const fn as_pragma(self) -> &'static str {
34        match self {
35            Self::Full => "FULL",
36            Self::Normal => "NORMAL",
37        }
38    }
39}
40
41/// Builds an [`crate::Engram`] instance.
42#[derive(Clone, Debug)]
43pub struct EngramBuilder {
44    pub(crate) storage: PathBuf,
45    pub(crate) memory_capacity: u64,
46    pub(crate) compression: Compression,
47    pub(crate) compression_threshold: usize,
48    pub(crate) compress_only_if_smaller: bool,
49    pub(crate) sqlite_connections: u32,
50    pub(crate) sqlite_synchronous: SqliteSynchronous,
51    pub(crate) cleanup_interval: Option<Duration>,
52}
53
54impl EngramBuilder {
55    pub(crate) fn new() -> Self {
56        Self {
57            storage: PathBuf::from("engram.db"),
58            memory_capacity: 64 * 1024 * 1024,
59            compression: Compression::default(),
60            compression_threshold: 1024,
61            compress_only_if_smaller: true,
62            sqlite_connections: 8,
63            sqlite_synchronous: SqliteSynchronous::Full,
64            cleanup_interval: None,
65        }
66    }
67
68    /// Selects the SQLite database file.
69    pub fn storage(mut self, path: impl AsRef<Path>) -> Self {
70        self.storage = path.as_ref().to_owned();
71        self
72    }
73
74    /// Sets the approximate maximum L1 capacity in weighted bytes.
75    pub fn memory_capacity(mut self, bytes: u64) -> Self {
76        self.memory_capacity = bytes.max(1);
77        self
78    }
79
80    /// Selects compression for newly persisted values.
81    pub fn compression(mut self, compression: Compression) -> Self {
82        self.compression = compression;
83        self
84    }
85
86    /// Compresses only values at least this large. The default is 1 KiB.
87    pub fn compression_threshold(mut self, bytes: usize) -> Self {
88        self.compression_threshold = bytes;
89        self
90    }
91
92    /// When enabled (the default), stores raw bytes when Zstd does not shrink them.
93    pub fn compress_only_if_smaller(mut self, enabled: bool) -> Self {
94        self.compress_only_if_smaller = enabled;
95        self
96    }
97
98    /// Sets the maximum number of SQLite connections used by this cache.
99    pub fn sqlite_connections(mut self, connections: u32) -> Self {
100        self.sqlite_connections = connections.max(1);
101        self
102    }
103
104    /// Selects SQLite's WAL durability setting. [`SqliteSynchronous::Full`] is the default.
105    pub fn sqlite_synchronous(mut self, synchronous: SqliteSynchronous) -> Self {
106        self.sqlite_synchronous = synchronous;
107        self
108    }
109
110    /// Enables periodic deletion of expired L2 rows. Disabled by default.
111    pub fn cleanup_interval(mut self, interval: Duration) -> Self {
112        self.cleanup_interval = (!interval.is_zero()).then_some(interval);
113        self
114    }
115
116    /// Opens the database and initializes its schema.
117    pub async fn build(self) -> crate::Result<crate::Engram> {
118        crate::Engram::from_builder(self).await
119    }
120}