1+ use super :: helpers:: OrderedHashMap ;
2+ use super :: CacheStorage ;
3+ use async_lock:: Mutex ;
14use async_trait:: async_trait;
2- use std:: {
3- collections:: { BTreeMap , HashMap } ,
4- fmt:: Debug ,
5- hash:: Hash ,
6- sync:: Arc ,
7- time:: SystemTime ,
8- } ;
9-
10- use async_lock:: { Mutex , RwLock } ;
11-
12- #[ async_trait]
13- pub trait CacheStorage < K , V > : Send + Sync + ' static {
14- async fn get ( & self , key : & K ) -> Option < V > ;
15-
16- async fn remove ( & mut self , key : & K ) -> Option < V > ;
17-
18- async fn insert ( & mut self , key : K , value : V ) -> Option < V > ;
19- }
20-
21- pub struct Cache < K , V > {
22- storage : Arc < RwLock < dyn CacheStorage < K , V > > > ,
23- }
24-
25- impl < K : ' static , V : ' static > Cache < K , V > {
26- pub fn new ( storage : impl CacheStorage < K , V > ) -> Self {
27- Self {
28- storage : Arc :: new ( RwLock :: new ( storage) ) ,
29- }
30- }
31- pub async fn get ( & mut self , key : & K ) -> Option < V > {
32- self . storage . read ( ) . await . get ( key) . await
33- }
34- pub async fn remove ( & mut self , key : & K ) -> Option < V > {
35- self . storage . write ( ) . await . remove ( key) . await
36- }
37- pub async fn insert ( & mut self , key : K , value : V ) -> Option < V > {
38- self . storage . write ( ) . await . insert ( key, value) . await
39- }
40- }
41-
42- // need to implement Clone manually because Mutex<dyn CacheStorage> doesn't implement Clone
43- impl < K , V > Clone for Cache < K , V > {
44- fn clone ( & self ) -> Self {
45- Self {
46- storage : self . storage . clone ( ) ,
47- }
48- }
49- }
50-
51- /// A hashmap that also maintains a BTreeMap of keys ordered by a given value
52- /// This is useful for structures that need fast O(1) lookups, but also need to evict the oldest or least recently used entries
53- struct OrderedHashMap < K , O , V > ( ( HashMap < K , ( O , V ) > , BTreeMap < O , Vec < K > > ) ) ;
54-
55- impl < K , O , V > OrderedHashMap < K , O , V > {
56- fn new ( ) -> Self {
57- Self ( ( HashMap :: new ( ) , BTreeMap :: new ( ) ) )
58- }
59- }
60-
61- impl < K : Hash + Eq + Clone , O : Ord + Copy , V > OrderedHashMap < K , O , V > {
62- fn len ( & self ) -> usize {
63- let ( lookup, _) = & self . 0 ;
64- lookup. len ( )
65- }
66- fn get ( & self , key : & K ) -> Option < & ( O , V ) > {
67- let ( lookup, _) = & self . 0 ;
68- lookup. get ( key)
69- }
70- fn get_key_value (
71- & self ,
72- selector : Box < dyn Fn ( & BTreeMap < O , Vec < K > > ) -> Option < ( & O , & Vec < K > ) > > ,
73- ) -> Option < ( & K , & O , & V ) > {
74- let ( lookup, ordered_lookup) = & self . 0 ;
75- selector ( ordered_lookup) . and_then ( |( _, keys) | {
76- keys. first ( )
77- . and_then ( |key| lookup. get ( key) . and_then ( |( o, v) | Some ( ( key, o, v) ) ) )
78- } )
79- }
80- /// gets the entry with the lowest order value
81- fn get_first_key_value ( & self ) -> Option < ( & K , & O , & V ) > {
82- self . get_key_value ( Box :: new ( |ordered_lookup| ordered_lookup. first_key_value ( ) ) )
83- }
84- /// gets the entry with the highest order value
85- fn get_last_key_value ( & self ) -> Option < ( & K , & O , & V ) > {
86- self . get_key_value ( Box :: new ( |ordered_lookup| ordered_lookup. last_key_value ( ) ) )
87- }
88- /// re-orders the entry with the given key
89- fn re_order ( & mut self , key : & K , new_order : O ) {
90- let ( lookup, order_lookup) = & mut self . 0 ;
91- if let Some ( ( old_order, _) ) = lookup. get ( key) {
92- // remove entry in btree
93- match order_lookup. get_mut ( old_order) {
94- Some ( keys) => {
95- keys. retain ( |k| k != key) ;
96- if keys. len ( ) == 0 {
97- order_lookup. remove ( old_order) ;
98- }
99- }
100- None => { }
101- }
102- }
103- order_lookup
104- . entry ( new_order)
105- . or_insert ( vec ! [ ] )
106- . push ( key. clone ( ) ) ;
107- lookup. get_mut ( key) . map ( |( o, _) | * o = new_order) ;
108- }
109- /// inserts a new entry with the given key and value and order
110- fn insert ( & mut self , key : K , value : V , order : O ) -> Option < V > {
111- let ( lookup, order_lookup) = & mut self . 0 ;
112-
113- if let Some ( ( old_order, _) ) = lookup. get ( & key) {
114- // remove entry in btree
115- match order_lookup. get_mut ( old_order) {
116- Some ( keys) => {
117- keys. retain ( |k| k != & key) ;
118- if keys. len ( ) == 0 {
119- order_lookup. remove ( old_order) ;
120- }
121- }
122- None => { }
123- }
124- }
125- order_lookup
126- . entry ( order)
127- . or_insert ( vec ! [ ] )
128- . push ( key. clone ( ) ) ;
129- lookup
130- . insert ( key, ( order, value) )
131- . and_then ( |( _, v) | Some ( v) )
132- }
133- /// removes the entry with the given key
134- fn remove ( & mut self , key : & K ) -> Option < ( O , V ) > {
135- let ( lookup, order_lookup) = & mut self . 0 ;
136- lookup. remove ( key) . and_then ( |( order, v) | {
137- match order_lookup. get_mut ( & order) {
138- Some ( keys) => {
139- keys. retain ( |k| k != key) ;
140- if keys. len ( ) == 0 {
141- order_lookup. remove ( & order) ;
142- }
143- }
144- None => { }
145- }
146- Some ( ( order, v) )
147- } )
148- }
149- /// removes the entry with the lowest order value
150- fn remove_first ( & mut self ) -> Option < ( K , O , V ) > {
151- let first_key = self . get_first_key_value ( ) . map ( |( k, _, _) | k. clone ( ) ) ;
152- if let Some ( first_key) = first_key {
153- self . remove ( & first_key)
154- . map ( |( order, v) | ( first_key, order, v) )
155- } else {
156- None
157- }
158- }
159- }
160-
5+ use std:: { hash:: Hash , sync:: Arc , time:: SystemTime } ;
1616/// A simple in-memory cache that uses timestamps to expire entries. Once the cache fills up, the oldest entry is evicted.
1627/// Uses a hashmap for lookups and a BTreeMap for ordering by age
1638pub struct MemCacheStorageTTL < K , V > {
@@ -180,7 +25,7 @@ impl<K, V> MemCacheStorageTTL<K, V> {
18025}
18126
18227#[ async_trait]
183- impl < K : Hash + Eq + Send + Sync + ' static + Clone + Debug , V : Clone + Send + Sync + ' static >
28+ impl < K : Hash + Eq + Send + Sync + ' static + Clone , V : Clone + Send + Sync + ' static >
18429 CacheStorage < K , V > for MemCacheStorageTTL < K , V >
18530{
18631 async fn get ( & self , key : & K ) -> Option < V > {
@@ -294,12 +139,12 @@ mod tests {
294139
295140 use std:: thread;
296141
142+ use super :: * ;
143+ use crate :: pool:: cache:: Cache ;
297144 use futures_executor:: block_on;
298145
299146 #[ rstest]
300147 fn test_cache_lru ( ) {
301- use super :: * ;
302-
303148 let mut cache = Cache :: new ( MemCacheStorageLRU :: new ( 2 ) ) ;
304149 block_on ( async {
305150 cache. insert ( "key" . to_string ( ) , "value" . to_string ( ) ) . await ;
@@ -325,8 +170,6 @@ mod tests {
325170
326171 #[ rstest]
327172 fn test_cache_ttl ( ) {
328- use super :: * ;
329-
330173 let mut cache = Cache :: new ( MemCacheStorageTTL :: new ( 2 , 5 ) ) ;
331174 block_on ( async {
332175 cache. insert ( "key" . to_string ( ) , "value" . to_string ( ) ) . await ;
0 commit comments