Created
November 29, 2018 15:43
-
-
Save zoidyzoidzoid/f3988bb0202db45451ad3e1365a4117e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pickle | |
import time | |
from django.core.cache.backends.base import DEFAULT_TIMEOUT | |
from django.core.cache.backends.memcached import MemcachedCache as _Cache | |
try: | |
import memcache | |
except ImportError: | |
_MintCache = None | |
else: | |
class _MintCache(_Cache): | |
_cache = None | |
"Memcached cache backend the sequel." | |
def __init__(self, server, params): | |
super(_MintCache, self).__init__(self, params) | |
self._client = memcache.Client(server.split(';')) | |
def get(self, key, default=None, version=None): | |
"""Fetch value, and if it's gonna expire soon, refresh it. | |
This has a race condition, since all requests that | |
happen after stale_after during the first client refreshing | |
it will also try refresh it. We should set a refreshing-{key} | |
key in the cache for the first client that is refreshing, ensuring | |
that only one client tries to refresh the key at a time. | |
""" | |
key = self.make_key(key, version=version) | |
val = self._cache.get(key) | |
lease_key = 'refreshing-{}'.format(key) | |
lease = self._cache.gets(lease_key) | |
if val is None: | |
val = default | |
else: | |
try: | |
stale_after, val = pickle.loads(val) | |
now = time.time() | |
if now > stale_after: | |
if lease: | |
# We're already refreshing the key, so let's | |
# return the stale value | |
val = default | |
else: | |
# cache_log("stale, getting lease") | |
# Try set lease key, but if another client has | |
# fetched the lease return default | |
got_lease = self._cache.cas(lease_key, 1, 60) | |
if got_lease: | |
self.set(key, val, 60) | |
val = default | |
except: | |
pass | |
return val | |
def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): | |
key = self.make_key(key, version=version) | |
if timeout is 0: | |
timeout = self.default_timeout | |
now = time.time() | |
val = pickle.dumps((now + timeout, value), 2) | |
self._cache.set(key, val, 7*86400) | |
def delete(self, key, version=None): | |
key = self.make_key(key, version=version) | |
self._cache.delete(key) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment