reifydb_runtime/cache/sync/
mod.rs1use std::hash::Hash;
5
6use cfg_if::cfg_if;
7
8#[cfg(not(reifydb_single_threaded))]
9pub(crate) mod native;
10#[cfg(reifydb_single_threaded)]
11pub(crate) mod wasm;
12
13cfg_if! {
14 if #[cfg(not(reifydb_single_threaded))] {
15 type LruImpl<K, V> = native::NativeLru<K, V>;
16 } else {
17 type LruImpl<K, V> = wasm::WasmLru<K, V>;
18 }
19}
20
21pub struct SyncLru<K, V>
22where
23 K: Hash + Eq + Clone + Send + Sync + 'static,
24 V: Clone + Send + Sync + 'static,
25{
26 inner: LruImpl<K, V>,
27}
28
29impl<K, V> SyncLru<K, V>
30where
31 K: Hash + Eq + Clone + Send + Sync + 'static,
32 V: Clone + Send + Sync + 'static,
33{
34 pub fn new(capacity: usize) -> Self {
35 assert!(capacity > 0, "LRU cache capacity must be greater than 0");
36 Self {
37 inner: LruImpl::new(capacity),
38 }
39 }
40
41 pub fn get(&self, key: &K) -> Option<V> {
42 self.inner.get(key)
43 }
44
45 pub fn put(&self, key: K, value: V) -> Option<V> {
46 self.inner.put(key, value)
47 }
48
49 pub fn remove(&self, key: &K) -> Option<V> {
50 self.inner.remove(key)
51 }
52
53 pub fn contains_key(&self, key: &K) -> bool {
54 self.inner.contains_key(key)
55 }
56
57 pub fn clear(&self) {
58 self.inner.clear();
59 }
60
61 pub fn len(&self) -> usize {
62 self.inner.len()
63 }
64
65 pub fn is_empty(&self) -> bool {
66 self.len() == 0
67 }
68
69 pub fn capacity(&self) -> usize {
70 self.inner.capacity()
71 }
72
73 pub fn run_pending_tasks(&self) {
74 self.inner.run_pending_tasks();
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::SyncLru;
81
82 #[test]
83 fn test_basic_operations() {
84 let cache = SyncLru::new(2);
85
86 assert_eq!(cache.put(1, "a"), None);
87 assert_eq!(cache.put(2, "b"), None);
88 assert_eq!(cache.get(&1), Some("a"));
89 assert_eq!(cache.get(&2), Some("b"));
90 cache.run_pending_tasks();
91 assert_eq!(cache.len(), 2);
92 }
93
94 #[test]
95 fn test_eviction() {
96 let cache = SyncLru::new(2);
97
98 cache.put(1, "a");
99 cache.put(2, "b");
100 let evicted = cache.put(3, "c");
101 cache.run_pending_tasks();
102
103 assert_eq!(evicted, None);
104 assert_eq!(cache.get(&1), None);
105 assert_eq!(cache.get(&2), Some("b"));
106 assert_eq!(cache.get(&3), Some("c"));
107 }
108
109 #[test]
110 fn test_lru_order() {
111 let cache = SyncLru::new(2);
112
113 cache.put(1, "a");
114 cache.put(2, "b");
115 cache.run_pending_tasks();
116 cache.get(&1); cache.run_pending_tasks();
118 cache.put(3, "c"); cache.run_pending_tasks();
120
121 assert_eq!(cache.get(&1), Some("a"));
122 assert_eq!(cache.get(&2), None);
123 assert_eq!(cache.get(&3), Some("c"));
124 }
125
126 #[test]
127 fn test_update_existing() {
128 let cache = SyncLru::new(2);
129
130 cache.put(1, "a");
131 let old = cache.put(1, "b");
132
133 assert_eq!(old, Some("a"));
134 assert_eq!(cache.get(&1), Some("b"));
135 cache.run_pending_tasks();
136 assert_eq!(cache.len(), 1);
137 }
138
139 #[test]
140 fn test_remove() {
141 let cache = SyncLru::new(2);
142
143 cache.put(1, "a");
144 cache.put(2, "b");
145 let removed = cache.remove(&1);
146
147 assert_eq!(removed, Some("a"));
148 assert_eq!(cache.get(&1), None);
149 cache.run_pending_tasks();
150 assert_eq!(cache.len(), 1);
151 }
152
153 #[test]
154 fn test_clear() {
155 let cache = SyncLru::new(2);
156
157 cache.put(1, "a");
158 cache.put(2, "b");
159 cache.clear();
160 cache.run_pending_tasks();
161
162 assert_eq!(cache.len(), 0);
163 assert!(cache.is_empty());
164 }
165
166 #[test]
167 fn test_contains_key() {
168 let cache = SyncLru::new(2);
169
170 cache.put(1, "a");
171 assert!(cache.contains_key(&1));
172 assert!(!cache.contains_key(&2));
173 }
174}