@@ -4,6 +4,8 @@ use std::hash::Hash;
4
4
use lru:: LruCache ;
5
5
#[ cfg( feature = "ttl-cache" ) ]
6
6
use std:: collections:: VecDeque ;
7
+ use std:: fmt:: Debug ;
8
+ use thiserror:: Error ;
7
9
#[ cfg( feature = "ttl-cache" ) ]
8
10
use std:: ops:: Add ;
9
11
#[ cfg( feature = "ttl-cache" ) ]
@@ -12,15 +14,26 @@ use tokio::time::{Instant, Duration};
12
14
pub trait CacheBacking < K , V >
13
15
where K : Eq + Hash + Sized + Clone + Send ,
14
16
V : Sized + Clone + Send {
15
- fn get_mut ( & mut self , key : & K ) -> Option < & mut V > ;
16
- fn get ( & mut self , key : & K ) -> Option < & V > ;
17
- fn set ( & mut self , key : K , value : V ) -> Option < V > ;
18
- fn remove ( & mut self , key : & K ) -> Option < V > ;
19
- fn contains_key ( & self , key : & K ) -> bool ;
20
- fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send + ' static > ) ;
21
- fn clear ( & mut self ) ;
17
+ type Meta : Clone + Send ;
18
+
19
+ fn get_mut ( & mut self , key : & K ) -> Result < Option < & mut V > , BackingError > ;
20
+ fn get ( & mut self , key : & K ) -> Result < Option < & V > , BackingError > ;
21
+ fn set ( & mut self , key : K , value : V , meta : Option < Self :: Meta > ) -> Result < Option < V > , BackingError > ;
22
+ fn remove ( & mut self , key : & K ) -> Result < Option < V > , BackingError > ;
23
+ fn contains_key ( & self , key : & K ) -> Result < bool , BackingError > ;
24
+ fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send + ' static > ) -> Result < ( ) , BackingError > ;
25
+ fn clear ( & mut self ) -> Result < ( ) , BackingError > ;
22
26
}
23
27
28
+ #[ derive( Debug , Clone , Error ) ]
29
+ pub enum BackingError {
30
+ #[ error( transparent) ]
31
+ TtlError ( #[ from] TtlError ) ,
32
+ }
33
+
34
+ #[ derive( Copy , Clone , Debug , Default ) ]
35
+ pub struct NoMeta { }
36
+
24
37
#[ cfg( feature = "lru-cache" ) ]
25
38
pub struct LruCacheBacking < K , V > {
26
39
lru : LruCache < K , V > ,
@@ -31,27 +44,29 @@ impl<
31
44
K : Eq + Hash + Sized + Clone + Send ,
32
45
V : Sized + Clone + Send
33
46
> CacheBacking < K , V > for LruCacheBacking < K , V > {
34
- fn get_mut ( & mut self , key : & K ) -> Option < & mut V > {
35
- self . lru . get_mut ( key)
47
+ type Meta = NoMeta ;
48
+
49
+ fn get_mut ( & mut self , key : & K ) -> Result < Option < & mut V > , BackingError > {
50
+ Ok ( self . lru . get_mut ( key) )
36
51
}
37
52
38
- fn get ( & mut self , key : & K ) -> Option < & V > {
39
- self . lru . get ( key)
53
+ fn get ( & mut self , key : & K ) -> Result < Option < & V > , BackingError > {
54
+ Ok ( self . lru . get ( key) )
40
55
}
41
56
42
- fn set ( & mut self , key : K , value : V ) -> Option < V > {
43
- self . lru . put ( key, value)
57
+ fn set ( & mut self , key : K , value : V , _meta : Option < Self :: Meta > ) -> Result < Option < V > , BackingError > {
58
+ Ok ( self . lru . put ( key, value) )
44
59
}
45
60
46
- fn remove ( & mut self , key : & K ) -> Option < V > {
47
- self . lru . pop ( key)
61
+ fn remove ( & mut self , key : & K ) -> Result < Option < V > , BackingError > {
62
+ Ok ( self . lru . pop ( key) )
48
63
}
49
64
50
- fn contains_key ( & self , key : & K ) -> bool {
51
- self . lru . contains ( & key. clone ( ) )
65
+ fn contains_key ( & self , key : & K ) -> Result < bool , BackingError > {
66
+ Ok ( self . lru . contains ( & key. clone ( ) ) )
52
67
}
53
68
54
- fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send > ) {
69
+ fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send > ) -> Result < ( ) , BackingError > {
55
70
let keys = self . lru . iter ( )
56
71
. filter_map ( |( key, value) | {
57
72
if predicate ( ( key, value) ) {
@@ -65,10 +80,12 @@ impl<
65
80
for key in keys. into_iter ( ) {
66
81
self . lru . pop ( & key) ;
67
82
}
83
+ Ok ( ( ) )
68
84
}
69
85
70
- fn clear ( & mut self ) {
86
+ fn clear ( & mut self ) -> Result < ( ) , BackingError > {
71
87
self . lru . clear ( ) ;
88
+ Ok ( ( ) )
72
89
}
73
90
}
74
91
@@ -114,51 +131,71 @@ impl<K> From<(K, Instant)> for TTlEntry<K> {
114
131
}
115
132
}
116
133
134
+ #[ derive( Debug , Clone , Error ) ]
135
+ pub enum TtlError {
136
+ #[ error( "The expiry for key not found" ) ]
137
+ ExpiryNotFound ,
138
+ #[ error( "No key for expiry matched key" ) ]
139
+ ExpiryKeyNotFound ,
140
+ }
141
+
142
+ #[ cfg( feature = "ttl-cache" ) ]
143
+ #[ derive( Debug , Copy , Clone ) ]
144
+ pub struct TtlMeta {
145
+ pub ttl : Duration ,
146
+ }
147
+
148
+ #[ cfg( feature = "ttl-cache" ) ]
149
+ impl From < Duration > for TtlMeta {
150
+ fn from ( ttl : Duration ) -> Self {
151
+ Self { ttl }
152
+ }
153
+ }
154
+
117
155
#[ cfg( feature = "ttl-cache" ) ]
118
156
impl <
119
157
K : Eq + Hash + Sized + Clone + Send ,
120
158
V : Sized + Clone + Send
121
159
> CacheBacking < K , V > for TtlCacheBacking < K , V > {
122
- fn get_mut ( & mut self , key : & K ) -> Option < & mut V > {
160
+ type Meta = TtlMeta ;
161
+
162
+ fn get_mut ( & mut self , key : & K ) -> Result < Option < & mut V > , BackingError > {
123
163
self . remove_old ( ) ;
124
- self . map . get_mut ( key)
125
- . map ( |( value, _) | value)
164
+ Ok ( self . map . get_mut ( key)
165
+ . map ( |( value, _) | value) )
126
166
}
127
167
128
- fn get ( & mut self , key : & K ) -> Option < & V > {
168
+ fn get ( & mut self , key : & K ) -> Result < Option < & V > , BackingError > {
129
169
self . remove_old ( ) ;
130
- self . map . get ( key)
131
- . map ( |( value, _) | value)
170
+ Ok ( self . map . get ( key)
171
+ . map ( |( value, _) | value) )
132
172
}
133
173
134
- fn set ( & mut self , key : K , value : V ) -> Option < V > {
174
+ fn set ( & mut self , key : K , value : V , meta : Option < Self :: Meta > ) -> Result < Option < V > , BackingError > {
135
175
self . remove_old ( ) ;
136
- let expiry = Instant :: now ( ) . add ( self . ttl ) ;
137
- let result = self . replace ( key. clone ( ) , value, expiry) ;
138
- match self . expiry_queue . binary_search_by_key ( & expiry, |entry| entry. expiry ) {
139
- Ok ( found) => {
140
- self . expiry_queue . insert ( found + 1 , ( key, expiry) . into ( ) ) ;
141
- }
142
- Err ( idx) => {
143
- self . expiry_queue . insert ( idx, ( key, expiry) . into ( ) ) ;
144
- }
145
- }
146
- result
176
+ let ttl = if let Some ( meta) = meta {
177
+ meta. ttl
178
+ } else {
179
+ self . ttl
180
+ } ;
181
+ let expiry = Instant :: now ( ) . add ( ttl) ;
182
+ let result = self . replace ( key. clone ( ) , value, expiry) ?;
183
+ Ok ( result)
147
184
}
148
185
149
- fn remove ( & mut self , key : & K ) -> Option < V > {
186
+ fn remove ( & mut self , key : & K ) -> Result < Option < V > , BackingError > {
150
187
self . remove_old ( ) ;
151
- self . remove_key ( key)
188
+ Ok ( self . remove_key ( key) ? )
152
189
}
153
190
154
- fn contains_key ( & self , key : & K ) -> bool {
191
+ fn contains_key ( & self , key : & K ) -> Result < bool , BackingError > {
155
192
// we cant clean old keys on this, since the self ref is not mutable :(
156
- self . map . get ( key)
193
+ Ok ( self . map . get ( key)
157
194
. filter ( |( _, expiry) | Instant :: now ( ) . lt ( expiry) )
158
- . is_some ( )
195
+ . is_some ( ) )
159
196
}
160
197
161
- fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send > ) {
198
+ fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send > ) -> Result < ( ) , BackingError > {
162
199
let keys = self . map . iter ( )
163
200
. filter_map ( |( key, ( value, _) ) | {
164
201
if predicate ( ( key, value) ) {
@@ -174,11 +211,13 @@ impl<
174
211
// optimize looping through expiry_queue multiple times?
175
212
self . expiry_queue . retain ( |entry| entry. key . ne ( & key) )
176
213
}
214
+ Ok ( ( ) )
177
215
}
178
216
179
- fn clear ( & mut self ) {
217
+ fn clear ( & mut self ) -> Result < ( ) , BackingError > {
180
218
self . expiry_queue . clear ( ) ;
181
219
self . map . clear ( ) ;
220
+ Ok ( ( ) )
182
221
}
183
222
}
184
223
@@ -203,34 +242,43 @@ impl<K: Eq + Hash + Sized + Clone + Send, V: Sized + Clone + Send> TtlCacheBacki
203
242
}
204
243
}
205
244
206
- fn replace ( & mut self , key : K , value : V , expiry : Instant ) -> Option < V > {
245
+ fn replace ( & mut self , key : K , value : V , expiry : Instant ) -> Result < Option < V > , TtlError > {
207
246
let entry = self . map . insert ( key. clone ( ) , ( value, expiry) ) ;
208
- self . cleanup_expiry ( entry, & key)
247
+ let res = self . cleanup_expiry ( entry, & key) ;
248
+ match self . expiry_queue . binary_search_by_key ( & expiry, |entry| entry. expiry ) {
249
+ Ok ( found) => {
250
+ self . expiry_queue . insert ( found + 1 , ( key, expiry) . into ( ) ) ;
251
+ }
252
+ Err ( idx) => {
253
+ self . expiry_queue . insert ( idx, ( key, expiry) . into ( ) ) ;
254
+ }
255
+ }
256
+ res
209
257
}
210
258
211
- fn remove_key ( & mut self , key : & K ) -> Option < V > {
259
+ fn remove_key ( & mut self , key : & K ) -> Result < Option < V > , TtlError > {
212
260
let entry = self . map . remove ( key) ;
213
261
self . cleanup_expiry ( entry, key)
214
262
}
215
263
216
- fn cleanup_expiry ( & mut self , entry : Option < ( V , Instant ) > , key : & K ) -> Option < V > {
264
+ fn cleanup_expiry ( & mut self , entry : Option < ( V , Instant ) > , key : & K ) -> Result < Option < V > , TtlError > {
217
265
if let Some ( ( value, old_expiry) ) = entry {
218
266
match self . expiry_queue . binary_search_by_key ( & old_expiry, |entry| entry. expiry ) {
219
267
Ok ( found) => {
220
268
let index = self . expiry_index_on_key_eq ( found, & old_expiry, key) ;
221
269
if let Some ( index) = index {
222
270
self . expiry_queue . remove ( index) ;
223
271
} else {
224
- // expiry not found (key)???
272
+ return Err ( TtlError :: ExpiryKeyNotFound ) ;
225
273
}
226
274
}
227
275
Err ( _) => {
228
- // expiry not found???
276
+ return Err ( TtlError :: ExpiryNotFound ) ;
229
277
}
230
278
}
231
- Some ( value)
279
+ Ok ( Some ( value) )
232
280
} else {
233
- None
281
+ Ok ( None )
234
282
}
235
283
}
236
284
@@ -274,32 +322,36 @@ impl<
274
322
K : Eq + Hash + Sized + Clone + Send ,
275
323
V : Sized + Clone + Send
276
324
> CacheBacking < K , V > for HashMapBacking < K , V > {
277
- fn get_mut ( & mut self , key : & K ) -> Option < & mut V > {
278
- self . map . get_mut ( key)
325
+ type Meta = NoMeta ;
326
+
327
+ fn get_mut ( & mut self , key : & K ) -> Result < Option < & mut V > , BackingError > {
328
+ Ok ( self . map . get_mut ( key) )
279
329
}
280
330
281
- fn get ( & mut self , key : & K ) -> Option < & V > {
282
- self . map . get ( key)
331
+ fn get ( & mut self , key : & K ) -> Result < Option < & V > , BackingError > {
332
+ Ok ( self . map . get ( key) )
283
333
}
284
334
285
- fn set ( & mut self , key : K , value : V ) -> Option < V > {
286
- self . map . insert ( key, value)
335
+ fn set ( & mut self , key : K , value : V , _meta : Option < Self :: Meta > ) -> Result < Option < V > , BackingError > {
336
+ Ok ( self . map . insert ( key, value) )
287
337
}
288
338
289
- fn remove ( & mut self , key : & K ) -> Option < V > {
290
- self . map . remove ( key)
339
+ fn remove ( & mut self , key : & K ) -> Result < Option < V > , BackingError > {
340
+ Ok ( self . map . remove ( key) )
291
341
}
292
342
293
- fn contains_key ( & self , key : & K ) -> bool {
294
- self . map . contains_key ( key)
343
+ fn contains_key ( & self , key : & K ) -> Result < bool , BackingError > {
344
+ Ok ( self . map . contains_key ( key) )
295
345
}
296
346
297
- fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send > ) {
347
+ fn remove_if ( & mut self , predicate : Box < dyn Fn ( ( & K , & V ) ) -> bool + Send > ) -> Result < ( ) , BackingError > {
298
348
self . map . retain ( |k, v| !predicate ( ( k, v) ) ) ;
349
+ Ok ( ( ) )
299
350
}
300
351
301
- fn clear ( & mut self ) {
352
+ fn clear ( & mut self ) -> Result < ( ) , BackingError > {
302
353
self . map . clear ( ) ;
354
+ Ok ( ( ) )
303
355
}
304
356
}
305
357
0 commit comments