1use lru::LruCache;
2use luct_core::store::{
3 AppendableStore, AsyncAppendableStore, AsyncOrderedStoreRead, AsyncSearchableStoreRead,
4 AsyncStoreRead, AsyncStoreWrite, OrderedStoreRead, SearchableStoreRead, Store, StoreBase,
5 StoreRead, StoreWrite,
6};
7use std::{
8 cell::RefCell,
9 fmt::Debug,
10 hash::Hash,
11 ops::{Deref, DerefMut},
12};
13
14pub struct LruCacheStore<S>
21where
22 S: StoreBase,
23{
24 cache: RefCell<LruCache<S::Key, S::Value>>,
25 inner: S,
26}
27
28impl<S> Debug for LruCacheStore<S>
29where
30 S: StoreBase<Key: Debug, Value: Debug> + Debug,
31{
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 f.debug_struct("LruCacheStore")
34 .field("inner", &self.inner)
35 .finish()
36 }
37}
38
39impl<S> Deref for LruCacheStore<S>
40where
41 S: StoreBase,
42{
43 type Target = S;
44
45 fn deref(&self) -> &Self::Target {
46 &self.inner
47 }
48}
49
50impl<S> DerefMut for LruCacheStore<S>
51where
52 S: Store,
53{
54 fn deref_mut(&mut self) -> &mut Self::Target {
55 &mut self.inner
56 }
57}
58
59impl<S> LruCacheStore<S>
60where
61 S: StoreBase<Key: Hash + Eq>,
62{
63 pub fn new(store: S, caps: usize) -> Self {
64 Self {
65 cache: RefCell::new(LruCache::new(caps.try_into().unwrap())),
66 inner: store,
67 }
68 }
69}
70
71impl<S> StoreBase for LruCacheStore<S>
72where
73 S: StoreBase,
74{
75 type Key = S::Key;
76 type Value = S::Value;
77}
78
79impl<S> StoreRead for LruCacheStore<S>
80where
81 S: StoreRead<Key: Clone + Hash + Eq, Value: Clone>,
82{
83 fn get(&self, key: &Self::Key) -> Option<Self::Value> {
84 if let Some(val) = self.cache.borrow_mut().get(key) {
85 Some(val.clone())
86 } else {
87 let val = self.inner.get(key)?;
88 self.cache.borrow_mut().put(key.clone(), val.clone());
89 Some(val)
90 }
91 }
92
93 fn len(&self) -> usize {
94 self.inner.len()
95 }
96}
97
98impl<S> StoreWrite for LruCacheStore<S>
99where
100 S: StoreWrite<Key: Hash + Eq>,
101{
102 fn insert(&self, key: Self::Key, value: Self::Value) {
103 self.cache.borrow_mut().pop(&key);
104 self.inner.insert(key, value);
105 }
106
107 fn delete(&self, key: &Self::Key) -> bool {
108 let contained = self.inner.delete(key);
109 self.cache.borrow_mut().pop(key);
110 contained
111 }
112}
113
114impl<S> OrderedStoreRead for LruCacheStore<S>
115where
116 S: OrderedStoreRead<Key: Clone + Hash, Value: Clone>,
117{
118 fn last(&self) -> Option<(Self::Key, Self::Value)> {
119 self.inner.last()
120 }
121}
122
123impl<S> AppendableStore for LruCacheStore<S>
124where
125 S: AppendableStore<Key: Clone + Hash, Value: Clone>,
126{
127 fn append(&self, value: Self::Value) -> Self::Key {
128 self.inner.append(value)
129 }
130}
131
132impl<S> SearchableStoreRead for LruCacheStore<S>
133where
134 S: SearchableStoreRead<Key: Clone + Hash, Value: Clone>,
135{
136 fn filter(
137 &self,
138 pred: impl FnMut(&Self::Key, &Self::Value) -> bool,
139 ) -> Vec<(Self::Key, Self::Value)> {
140 self.inner.filter(pred)
141 }
142
143 fn find(
144 &self,
145 pred: impl FnMut(&Self::Key, &Self::Value) -> bool,
146 ) -> Option<(Self::Key, Self::Value)> {
147 self.inner.find(pred)
148 }
149}
150
151impl<S> AsyncStoreRead for LruCacheStore<S>
152where
153 S: AsyncStoreRead<Key: Clone + Hash + Eq, Value: Clone>,
154{
155 async fn get(&self, key: Self::Key) -> Option<Self::Value> {
156 if let Some(val) = self.cache.borrow_mut().get(&key) {
157 Some(val.clone())
158 } else {
159 let val = self.inner.get(key.clone()).await?;
160 self.cache.borrow_mut().put(key, val.clone());
161 Some(val)
162 }
163 }
164
165 async fn len(&self) -> usize {
166 self.inner.len().await
167 }
168}
169
170impl<S> AsyncStoreWrite for LruCacheStore<S>
171where
172 S: AsyncStoreWrite<Key: Clone + Hash + Eq, Value: Clone>,
173{
174 async fn insert(&self, key: Self::Key, value: Self::Value) {
175 self.cache.borrow_mut().pop(&key);
176 self.inner.insert(key, value).await
177 }
178
179 async fn delete(&self, key: Self::Key) -> bool {
180 let contained = self.inner.delete(key.clone()).await;
181 self.cache.borrow_mut().pop(&key);
182 contained
183 }
184}
185
186impl<S> AsyncOrderedStoreRead for LruCacheStore<S>
187where
188 S: AsyncOrderedStoreRead<Key: Clone + Hash, Value: Clone>,
189{
190 async fn last(&self) -> Option<(Self::Key, Self::Value)> {
191 self.inner.last().await
192 }
193}
194
195impl<S> AsyncAppendableStore for LruCacheStore<S>
196where
197 S: AsyncAppendableStore<Key: Clone + Hash, Value: Clone>,
198{
199 async fn append(&self, value: Self::Value) -> Self::Key {
200 self.inner.append(value).await
201 }
202}
203
204impl<S> AsyncSearchableStoreRead for LruCacheStore<S>
205where
206 S: AsyncSearchableStoreRead<Key: Clone + Hash, Value: Clone>,
207{
208 async fn filter(
209 &self,
210 pred: impl FnMut(&Self::Key, &Self::Value) -> bool,
211 ) -> Vec<(Self::Key, Self::Value)> {
212 self.inner.filter(pred).await
213 }
214
215 async fn find(
216 &self,
217 pred: impl FnMut(&Self::Key, &Self::Value) -> bool,
218 ) -> Option<(Self::Key, Self::Value)> {
219 self.inner.find(pred).await
220 }
221}
222
223#[cfg(test)]
224mod tests {
225 use super::*;
226 use luct_core::store::MemoryStore;
227 use luct_test::store::{ordered_store_test, searchable_store_test, store_test};
228
229 #[test]
230 fn lru_cache_store() {
231 let store = LruCacheStore::new(MemoryStore::<u64, String>::default(), 1000);
232 store_test(store);
233 }
234
235 #[test]
236 fn lru_cache_ordered_store() {
237 let store = LruCacheStore::new(MemoryStore::<u64, String>::default(), 1000);
238 ordered_store_test(store);
239 }
240
241 #[test]
242 fn lru_cache_searchable_store() {
243 let store = LruCacheStore::new(MemoryStore::<u64, String>::default(), 1000);
244 searchable_store_test(store);
245 }
246}