Skip to content

Instantly share code, notes, and snippets.

@zoidyzoidzoid
Created November 29, 2018 15:43
Show Gist options
  • Select an option

  • Save zoidyzoidzoid/f3988bb0202db45451ad3e1365a4117e to your computer and use it in GitHub Desktop.

Select an option

Save zoidyzoidzoid/f3988bb0202db45451ad3e1365a4117e to your computer and use it in GitHub Desktop.

Revisions

  1. zoidyzoidzoid created this gist Nov 29, 2018.
    67 changes: 67 additions & 0 deletions mint_cache_v2.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,67 @@
    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)