11use super :: storage:: OrderedHashMap ;
22use super :: CacheStrategy ;
3- use async_lock:: Mutex ;
4- use async_trait:: async_trait;
5- use std:: { collections:: BTreeMap , fmt:: Debug , hash:: Hash , sync:: Arc , time:: SystemTime } ;
3+ use std:: {
4+ collections:: BTreeMap ,
5+ fmt:: Debug ,
6+ hash:: Hash ,
7+ ops:: Deref ,
8+ sync:: { Arc , Mutex } ,
9+ time:: SystemTime ,
10+ } ;
611
712/// A simple struct to hold a value and the expiry offset
813/// needed because items can be inserted with custom ttl values
@@ -50,89 +55,94 @@ impl<K: Eq + Hash + Clone + Send + Sync + 'static, V: Clone + Send + Sync + 'sta
5055 }
5156}
5257
53- #[ async_trait]
5458impl < K : Send + Sync + ' static , V : Send + Sync + ' static > CacheStrategy < K , V >
5559 for Arc < dyn CacheStrategy < K , V > >
5660{
57- async fn get ( & self , key : & K ) -> Option < V > {
58- self . get ( key) . await
61+ fn get ( & self , key : & K ) -> Option < V > {
62+ self . deref ( ) . get ( key)
5963 }
60- async fn remove ( & mut self , key : & K ) -> Option < V > {
61- self . remove ( key) . await
64+ fn remove ( & self , key : & K ) -> Option < V > {
65+ self . deref ( ) . remove ( key)
6266 }
63- async fn insert ( & mut self , key : K , value : V , custom_exp_offset : Option < u128 > ) -> Option < V > {
64- self . insert ( key, value, custom_exp_offset) . await
67+ fn insert ( & self , key : K , value : V , custom_exp_offset : Option < u128 > ) -> Option < V > {
68+ self . deref ( ) . insert ( key, value, custom_exp_offset)
6569 }
6670}
6771
68- #[ async_trait]
6972impl < K : Hash + Eq + Send + Sync + ' static + Clone + Debug , V : Clone + Send + Sync + ' static >
7073 CacheStrategy < K , V > for CacheStrategyTTL < K , V >
7174{
72- async fn get ( & self , key : & K ) -> Option < V > {
73- let mut store_lock = self . store . lock ( ) . await ;
74- let current_time = SystemTime :: now ( )
75- . duration_since ( self . create_time )
76- . unwrap ( )
77- . as_millis ( ) ;
78- let get_res = match store_lock. get ( key) {
79- Some ( ( ts, v) ) => {
80- if current_time < * ts {
81- Some ( ( * ts, v. clone ( ) ) )
82- } else {
83- store_lock. remove ( key) ;
84- None
75+ fn get ( & self , key : & K ) -> Option < V > {
76+ if let Some ( mut store_lock) = self . store . lock ( ) . ok ( ) {
77+ let current_time = SystemTime :: now ( )
78+ . duration_since ( self . create_time )
79+ . unwrap ( )
80+ . as_millis ( ) ;
81+ let get_res = match store_lock. get ( key) {
82+ Some ( ( ts, v) ) => {
83+ if current_time < * ts {
84+ Some ( ( * ts, v. clone ( ) ) )
85+ } else {
86+ store_lock. remove ( key) ;
87+ None
88+ }
8589 }
90+ None => None ,
91+ } ;
92+ // update the timestamp if the entry is still valid
93+ if let Some ( ( _, ref v) ) = get_res {
94+ store_lock. re_order ( key, current_time + v. expire_offset ) ;
8695 }
87- None => None ,
88- } ;
89- // update the timestamp if the entry is still valid
90- if let Some ( ( _, ref v) ) = get_res {
91- store_lock. re_order ( key, current_time + v. expire_offset ) ;
96+ return get_res. map ( |( _, v) | v. value ) ;
9297 }
93- get_res . map ( | ( _ , v ) | v . value )
98+ None
9499 }
95- async fn remove ( & mut self , key : & K ) -> Option < V > {
96- self . store . lock ( ) . await . remove ( key) . map ( |( _, v) | v. value )
100+ fn remove ( & self , key : & K ) -> Option < V > {
101+ if let Some ( mut store) = self . store . lock ( ) . ok ( ) {
102+ return store. remove ( key) . map ( |( _, v) | v. value ) ;
103+ }
104+ None
97105 }
98106
99- async fn insert ( & mut self , key : K , value : V , custom_exp_offset : Option < u128 > ) -> Option < V > {
100- let mut store_lock = self . store . lock ( ) . await ;
101- let current_ts = SystemTime :: now ( )
102- . duration_since ( self . create_time )
103- . unwrap ( )
104- . as_millis ( ) ;
105-
106- // remove expired entries
107- while store_lock. len ( ) > 0
108- && store_lock
109- . get_first_key_value ( )
110- . map ( |( _, ts, _) | ts. clone ( ) < current_ts)
111- . unwrap_or ( false )
112- {
113- store_lock. remove_first ( ) ;
114- }
107+ fn insert ( & self , key : K , value : V , custom_exp_offset : Option < u128 > ) -> Option < V > {
108+ if let Some ( mut store_lock) = self . store . lock ( ) . ok ( ) {
109+ let current_ts = SystemTime :: now ( )
110+ . duration_since ( self . create_time )
111+ . unwrap ( )
112+ . as_millis ( ) ;
115113
116- // remove the oldest item if the cache is still full
117- if store_lock. len ( ) >= self . capacity && store_lock. get ( & key) . is_none ( ) {
118- // remove the oldest item
119- let removal_key = store_lock. get_first_key_value ( ) . map ( |( k, _, _) | k. clone ( ) ) ;
120- if let Some ( removal_key) = removal_key {
121- store_lock. remove ( & removal_key) ;
114+ // remove expired entries
115+ while store_lock. len ( ) > 0
116+ && store_lock
117+ . get_first_key_value ( )
118+ . map ( |( _, ts, _) | ts. clone ( ) < current_ts)
119+ . unwrap_or ( false )
120+ {
121+ store_lock. remove_first ( ) ;
122122 }
123- } ;
124123
125- let exp_offset = custom_exp_offset. unwrap_or ( self . expire_after ) ;
126- store_lock
127- . insert (
128- key,
129- TTLCacheItem {
130- value : value,
131- expire_offset : exp_offset,
132- } ,
133- current_ts + exp_offset,
134- )
135- . map ( |v| v. value )
124+ // remove the oldest item if the cache is still full
125+ if store_lock. len ( ) >= self . capacity && store_lock. get ( & key) . is_none ( ) {
126+ // remove the oldest item
127+ let removal_key = store_lock. get_first_key_value ( ) . map ( |( k, _, _) | k. clone ( ) ) ;
128+ if let Some ( removal_key) = removal_key {
129+ store_lock. remove ( & removal_key) ;
130+ }
131+ } ;
132+
133+ let exp_offset = custom_exp_offset. unwrap_or ( self . expire_after ) ;
134+ return store_lock
135+ . insert (
136+ key,
137+ TTLCacheItem {
138+ value : value,
139+ expire_offset : exp_offset,
140+ } ,
141+ current_ts + exp_offset,
142+ )
143+ . map ( |v| v. value ) ;
144+ }
145+ None
136146 }
137147}
138148
@@ -158,53 +168,31 @@ mod tests {
158168 let caches = vec ! [ cache, fs_cache] ;
159169 block_on ( async {
160170 for cache in caches {
161- cache
162- . insert ( "key" . to_string ( ) , "value" . to_string ( ) , None )
163- . await ;
164- assert_eq ! (
165- cache. get( & "key" . to_string( ) ) . await ,
166- Some ( "value" . to_string( ) )
167- ) ;
168- cache
169- . insert ( "key1" . to_string ( ) , "value1" . to_string ( ) , None )
170- . await ;
171- cache
172- . insert ( "key2" . to_string ( ) , "value2" . to_string ( ) , None )
173- . await ;
174- assert_eq ! ( cache. get( & "key" . to_string( ) ) . await , None ) ;
175- cache
176- . insert ( "key3" . to_string ( ) , "value3" . to_string ( ) , None )
177- . await ;
178- cache. get ( & "key2" . to_string ( ) ) . await ;
179- cache
180- . insert ( "key4" . to_string ( ) , "value4" . to_string ( ) , None )
181- . await ;
171+ cache. insert ( "key" . to_string ( ) , "value" . to_string ( ) , None ) ;
172+ assert_eq ! ( cache. get( & "key" . to_string( ) ) , Some ( "value" . to_string( ) ) ) ;
173+ cache. insert ( "key1" . to_string ( ) , "value1" . to_string ( ) , None ) ;
174+ cache. insert ( "key2" . to_string ( ) , "value2" . to_string ( ) , None ) ;
175+ assert_eq ! ( cache. get( & "key" . to_string( ) ) , None ) ;
176+ cache. insert ( "key3" . to_string ( ) , "value3" . to_string ( ) , None ) ;
177+ cache. get ( & "key2" . to_string ( ) ) ;
178+ cache. insert ( "key4" . to_string ( ) , "value4" . to_string ( ) , None ) ;
182179 // key2 should not be evicted because of LRU
183180 assert_eq ! (
184- cache. remove( & "key2" . to_string( ) ) . await ,
181+ cache. remove( & "key2" . to_string( ) ) ,
185182 Some ( "value2" . to_string( ) )
186183 ) ;
187184 // key3 should be evicted because it was bumped to back after key2 was accessed
188- assert_eq ! ( cache. get( & "key3" . to_string( ) ) . await , None ) ;
189- cache
190- . insert ( "key5" . to_string ( ) , "value5" . to_string ( ) , None )
191- . await ;
185+ assert_eq ! ( cache. get( & "key3" . to_string( ) ) , None ) ;
186+ cache. insert ( "key5" . to_string ( ) , "value5" . to_string ( ) , None ) ;
192187 thread:: sleep ( std:: time:: Duration :: from_millis ( 6 ) ) ;
193- assert_eq ! ( cache. get( & "key5" . to_string( ) ) . await , None ) ;
188+ assert_eq ! ( cache. get( & "key5" . to_string( ) ) , None ) ;
194189 // test ttl config
195- cache
196- . insert ( "key6" . to_string ( ) , "value6" . to_string ( ) , Some ( 1 ) )
197- . await ;
198- cache
199- . insert ( "key7" . to_string ( ) , "value7" . to_string ( ) , None )
200- . await ;
190+ cache. insert ( "key6" . to_string ( ) , "value6" . to_string ( ) , Some ( 1 ) ) ;
191+ cache. insert ( "key7" . to_string ( ) , "value7" . to_string ( ) , None ) ;
201192 // wait until value6 expires
202193 thread:: sleep ( std:: time:: Duration :: from_millis ( 1 ) ) ;
203- assert_eq ! ( cache. get( & "key6" . to_string( ) ) . await , None ) ;
204- assert_eq ! (
205- cache. get( & "key7" . to_string( ) ) . await ,
206- Some ( "value7" . to_string( ) )
207- ) ;
194+ assert_eq ! ( cache. get( & "key6" . to_string( ) ) , None ) ;
195+ assert_eq ! ( cache. get( & "key7" . to_string( ) ) , Some ( "value7" . to_string( ) ) ) ;
208196 }
209197 std:: fs:: remove_dir_all ( cache_location) . unwrap ( ) ;
210198 } ) ;
0 commit comments