4
4
.. versionadded:: 2016.11.0
5
5
"""
6
6
7
+ import datetime
7
8
import logging
8
9
import time
9
10
@@ -119,7 +120,7 @@ def cache(self, bank, key, fun, loop_fun=None, **kwargs):
119
120
120
121
return data
121
122
122
- def store (self , bank , key , data ):
123
+ def store (self , bank , key , data , expires = None ):
123
124
"""
124
125
Store data using the specified module
125
126
@@ -136,12 +137,26 @@ def store(self, bank, key, data):
136
137
The data which will be stored in the cache. This data should be
137
138
in a format which can be serialized by msgpack.
138
139
139
- :raises SaltCacheError:
140
+ :param expires:
141
+ how many seconds from now the data should be considered stale.
142
+
143
+ :raises SaltCacheError:
140
144
Raises an exception if cache driver detected an error accessing data
141
145
in the cache backend (auth, permissions, etc).
142
146
"""
143
147
fun = f"{ self .driver } .store"
144
- return self .modules [fun ](bank , key , data , ** self ._kwargs )
148
+ try :
149
+ return self .modules [fun ](bank , key , data , expires = expires , ** self ._kwargs )
150
+ except TypeError :
151
+ # if the backing store doesnt natively support expiry, we handle it as a fallback
152
+ if expires :
153
+ expires_at = datetime .datetime .now ().astimezone () + datetime .timedelta (
154
+ seconds = expires
155
+ )
156
+ expires_at = int (expires_at .timestamp ())
157
+ return self .modules [fun ](
158
+ bank , key , {"data" : data , "_expires" : expires_at }, ** self ._kwargs
159
+ )
145
160
146
161
def fetch (self , bank , key ):
147
162
"""
@@ -165,7 +180,17 @@ def fetch(self, bank, key):
165
180
in the cache backend (auth, permissions, etc).
166
181
"""
167
182
fun = f"{ self .driver } .fetch"
168
- return self .modules [fun ](bank , key , ** self ._kwargs )
183
+ ret = self .modules [fun ](bank , key , ** self ._kwargs )
184
+
185
+ # handle fallback if necessary
186
+ if isinstance (ret , dict ) and set (ret .keys ()) == {"data" , "_expires" }:
187
+ now = datetime .datetime .now ().astimezone ()
188
+ if ret ["_expires" ] > now :
189
+ return ret ["data" ]
190
+ else :
191
+ return {}
192
+ else :
193
+ return ret
169
194
170
195
def updated (self , bank , key ):
171
196
"""
@@ -309,19 +334,21 @@ def fetch(self, bank, key):
309
334
now = time .time ()
310
335
record = self .storage .pop ((bank , key ), None )
311
336
# Have a cached value for the key
312
- if record is not None and record [0 ] + self .expire >= now :
313
- if self .debug :
314
- self .hit += 1
315
- log .debug (
316
- "MemCache stats (call/hit/rate): %s/%s/%s" ,
317
- self .call ,
318
- self .hit ,
319
- float (self .hit ) / self .call ,
320
- )
321
- # update atime and return
322
- record [0 ] = now
323
- self .storage [(bank , key )] = record
324
- return record [1 ]
337
+ if record is not None :
338
+ (created_at , expires , data ) = record
339
+ if (created_at + (expires or self .expire )) >= now :
340
+ if self .debug :
341
+ self .hit += 1
342
+ log .debug (
343
+ "MemCache stats (call/hit/rate): %s/%s/%s" ,
344
+ self .call ,
345
+ self .hit ,
346
+ float (self .hit ) / self .call ,
347
+ )
348
+ # update atime and return
349
+ record [0 ] = now
350
+ self .storage [(bank , key )] = record
351
+ return record [1 ]
325
352
326
353
# Have no value for the key or value is expired
327
354
data = super ().fetch (bank , key )
@@ -333,15 +360,15 @@ def fetch(self, bank, key):
333
360
self .storage [(bank , key )] = [now , data ]
334
361
return data
335
362
336
- def store (self , bank , key , data ):
363
+ def store (self , bank , key , data , expires = None ):
337
364
self .storage .pop ((bank , key ), None )
338
- super ().store (bank , key , data )
365
+ super ().store (bank , key , data , expires )
339
366
if len (self .storage ) >= self .max :
340
367
if self .cleanup :
341
368
MemCache .__cleanup (self .expire )
342
369
if len (self .storage ) >= self .max :
343
370
self .storage .popitem (last = False )
344
- self .storage [(bank , key )] = [time .time (), data ]
371
+ self .storage [(bank , key )] = [time .time (), expires , data ]
345
372
346
373
def flush (self , bank , key = None ):
347
374
if key is None :
0 commit comments