reifydb_cdc/compact/
cache.rs1use std::sync::Arc;
5
6use reifydb_core::{common::CommitVersion, interface::cdc::Cdc};
7use reifydb_runtime::cache::sync::SyncLru;
8
9#[derive(Clone)]
10pub struct BlockCache {
11 inner: Arc<SyncLru<CommitVersion, Arc<Vec<Cdc>>>>,
12}
13
14impl BlockCache {
15 pub const DEFAULT_CAPACITY: usize = 8;
16
17 pub fn new(capacity: usize) -> Self {
18 Self {
19 inner: Arc::new(SyncLru::new(capacity.max(1))),
20 }
21 }
22
23 pub fn get(&self, key: CommitVersion) -> Option<Arc<Vec<Cdc>>> {
24 self.inner.get(&key)
25 }
26
27 pub fn put(&self, key: CommitVersion, value: Arc<Vec<Cdc>>) {
28 let _ = self.inner.put(key, value);
29 }
30
31 pub fn remove(&self, key: CommitVersion) {
32 let _ = self.inner.remove(&key);
33 }
34
35 pub fn clear(&self) {
36 self.inner.clear();
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 fn cv(n: u64) -> CommitVersion {
45 CommitVersion(n)
46 }
47
48 fn empty_block() -> Arc<Vec<Cdc>> {
49 Arc::new(Vec::new())
50 }
51
52 #[test]
53 fn put_then_get_returns_inserted_arc() {
54 let cache = BlockCache::new(4);
55 let block = empty_block();
56 cache.put(cv(1), block.clone());
57
58 let got = cache.get(cv(1)).expect("entry should be present");
59 assert!(Arc::ptr_eq(&got, &block));
60 }
61
62 #[test]
63 fn get_returns_none_for_missing_key() {
64 let cache = BlockCache::new(4);
65 assert!(cache.get(cv(1)).is_none());
66
67 cache.put(cv(1), empty_block());
68 assert!(cache.get(cv(2)).is_none());
69 }
70
71 #[test]
72 fn put_overwrites_existing_value() {
73 let cache = BlockCache::new(4);
74 let first = empty_block();
75 let second = empty_block();
76 assert!(!Arc::ptr_eq(&first, &second));
77
78 cache.put(cv(1), first);
79 cache.put(cv(1), second.clone());
80
81 let got = cache.get(cv(1)).expect("entry should be present");
82 assert!(Arc::ptr_eq(&got, &second));
83 }
84
85 #[test]
86 fn remove_drops_value() {
87 let cache = BlockCache::new(4);
88 cache.put(cv(1), empty_block());
89
90 cache.remove(cv(1));
91 assert!(cache.get(cv(1)).is_none());
92 }
93
94 #[test]
95 fn remove_missing_key_is_noop() {
96 let cache = BlockCache::new(4);
97 cache.remove(cv(99));
98
99 cache.put(cv(1), empty_block());
100 cache.remove(cv(99));
101 assert!(cache.get(cv(1)).is_some());
102 }
103
104 #[test]
105 fn clear_empties_cache() {
106 let cache = BlockCache::new(4);
107 cache.put(cv(1), empty_block());
108 cache.put(cv(2), empty_block());
109 cache.put(cv(3), empty_block());
110
111 cache.clear();
112
113 assert!(cache.get(cv(1)).is_none());
114 assert!(cache.get(cv(2)).is_none());
115 assert!(cache.get(cv(3)).is_none());
116 }
117
118 #[test]
119 fn eviction_drops_least_recently_used() {
120 let cache = BlockCache::new(2);
121 cache.put(cv(1), empty_block());
122 cache.put(cv(2), empty_block());
123 cache.put(cv(3), empty_block());
124 cache.inner.run_pending_tasks();
125
126 assert!(cache.get(cv(1)).is_none(), "oldest entry should be evicted");
127 assert!(cache.get(cv(2)).is_some());
128 assert!(cache.get(cv(3)).is_some());
129 }
130
131 #[test]
132 fn get_promotes_recency_so_old_key_survives() {
133 let cache = BlockCache::new(2);
134 cache.put(cv(1), empty_block());
135 cache.put(cv(2), empty_block());
136 cache.inner.run_pending_tasks();
137
138 let _ = cache.get(cv(1));
139 cache.inner.run_pending_tasks();
140
141 cache.put(cv(3), empty_block());
142 cache.inner.run_pending_tasks();
143
144 assert!(cache.get(cv(1)).is_some(), "recently-touched key should survive");
145 assert!(cache.get(cv(2)).is_none(), "untouched older key should be evicted");
146 assert!(cache.get(cv(3)).is_some());
147 }
148
149 #[test]
150 fn new_with_zero_capacity_is_clamped_and_usable() {
151 let cache = BlockCache::new(0);
152 cache.put(cv(1), empty_block());
153 assert!(cache.get(cv(1)).is_some());
154 }
155
156 #[test]
157 fn clone_shares_backing_storage() {
158 let a = BlockCache::new(4);
159 let b = a.clone();
160
161 let block = empty_block();
162 a.put(cv(1), block.clone());
163
164 let got = b.get(cv(1)).expect("clone should see writes from original");
165 assert!(Arc::ptr_eq(&got, &block));
166 }
167}