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