Skip to content

Instantly share code, notes, and snippets.

@zoidyzoidzoid
Created November 29, 2018 15:43
Show Gist options
  • Save zoidyzoidzoid/f3988bb0202db45451ad3e1365a4117e to your computer and use it in GitHub Desktop.
Save zoidyzoidzoid/f3988bb0202db45451ad3e1365a4117e to your computer and use it in GitHub Desktop.
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