1use std::path::PathBuf;
6use std::time::Duration;
7
8pub use kevy_persist::Fsync as AppendFsync;
9pub use kevy_store::EvictionPolicy;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum TtlReaperMode {
14 Background,
17 Manual,
21}
22
23#[derive(Debug, Clone)]
26pub struct Config {
27 pub maxmemory: u64,
29 pub eviction_policy: EvictionPolicy,
31 pub data_dir: Option<PathBuf>,
33 pub aof: bool,
36 pub appendfsync: AppendFsync,
38 pub snapshot_filename: String,
40 pub aof_filename: String,
42 pub ttl_reaper: TtlReaperMode,
44 pub reaper_interval: Duration,
46 pub reaper_samples: usize,
48 pub reaper_max_rounds: u32,
50}
51
52impl Default for Config {
53 fn default() -> Self {
54 Self {
55 maxmemory: 0,
56 eviction_policy: EvictionPolicy::NoEviction,
57 data_dir: None,
58 aof: true,
59 appendfsync: AppendFsync::EverySec,
60 snapshot_filename: String::from("dump-0.rdb"),
61 aof_filename: String::from("aof-0.aof"),
62 ttl_reaper: TtlReaperMode::Background,
63 reaper_interval: Duration::from_millis(100),
64 reaper_samples: 20,
65 reaper_max_rounds: 16,
66 }
67 }
68}
69
70impl Config {
71 pub fn with_persist(mut self, dir: impl Into<PathBuf>) -> Self {
75 self.data_dir = Some(dir.into());
76 self
77 }
78
79 pub fn without_aof(mut self) -> Self {
82 self.aof = false;
83 self
84 }
85
86 pub fn with_max_memory(mut self, bytes: u64) -> Self {
88 self.maxmemory = bytes;
89 self
90 }
91
92 pub fn with_eviction(mut self, policy: EvictionPolicy) -> Self {
94 self.eviction_policy = policy;
95 self
96 }
97
98 pub fn with_appendfsync(mut self, fsync: AppendFsync) -> Self {
100 self.appendfsync = fsync;
101 self
102 }
103
104 pub fn with_ttl_reaper_manual(mut self) -> Self {
108 self.ttl_reaper = TtlReaperMode::Manual;
109 self
110 }
111
112 pub fn with_reaper_interval(mut self, iv: Duration) -> Self {
114 self.reaper_interval = iv;
115 self
116 }
117
118 pub fn with_snapshot_filename(mut self, name: impl Into<String>) -> Self {
120 self.snapshot_filename = name.into();
121 self
122 }
123
124 pub fn with_aof_filename(mut self, name: impl Into<String>) -> Self {
126 self.aof_filename = name.into();
127 self
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 #[test]
136 fn default_is_pure_in_memory() {
137 let c = Config::default();
138 assert_eq!(c.maxmemory, 0);
139 assert!(c.data_dir.is_none());
140 assert_eq!(c.ttl_reaper, TtlReaperMode::Background);
141 assert!(c.aof);
142 }
143
144 #[test]
145 fn builder_chains() {
146 let c = Config::default()
147 .with_persist("/tmp/foo")
148 .with_max_memory(1024)
149 .with_eviction(EvictionPolicy::AllKeysLru)
150 .with_ttl_reaper_manual()
151 .with_appendfsync(AppendFsync::Always);
152 assert_eq!(c.data_dir.as_deref(), Some(std::path::Path::new("/tmp/foo")));
153 assert_eq!(c.maxmemory, 1024);
154 assert_eq!(c.eviction_policy, EvictionPolicy::AllKeysLru);
155 assert_eq!(c.ttl_reaper, TtlReaperMode::Manual);
156 }
157
158 #[test]
159 fn without_aof_disables_logging_path() {
160 let c = Config::default().with_persist("/tmp/foo").without_aof();
161 assert!(c.data_dir.is_some());
162 assert!(!c.aof);
163 }
164}