Ticket #12399: memcached-timeout-fixes-with-tests-r12394.diff

File memcached-timeout-fixes-with-tests-r12394.diff, 2.9 KB (added by gciotta, 14 years ago)

With tests, tested against today's r12394

  • django/core/cache/backends/memcached.py

     
    11"Memcached cache backend"
    22
     3import time
     4
    35from django.core.cache.backends.base import BaseCache, InvalidCacheBackendError
    46from django.utils.encoding import smart_unicode, smart_str
    57
     
    1618        BaseCache.__init__(self, params)
    1719        self._cache = memcache.Client(server.split(';'))
    1820
     21    def _get_memcache_timeout(self, timeout):
     22        """
     23        Memcached deals with long (> 30 days) timeouts in a special
     24        way. Call this function to obtain a safe value for your timeout.
     25        """
     26        timeout = timeout or self.default_timeout
     27        if timeout > 2592000: # 60*60*24*30, 30 days
     28            # See http://code.google.com/p/memcached/wiki/FAQ
     29            # "You can set expire times up to 30 days in the future. After that
     30            # memcached interprets it as a date, and will expire the item after
     31            # said date. This is a simple (but obscure) mechanic."
     32            #
     33            # This means that we have to switch to absolute timestamps.
     34            timeout += int(time.time())
     35        return timeout
     36
    1937    def add(self, key, value, timeout=0):
    2038        if isinstance(value, unicode):
    2139            value = value.encode('utf-8')
    22         return self._cache.add(smart_str(key), value, timeout or self.default_timeout)
     40        return self._cache.add(smart_str(key), value, self._get_memcache_timeout(timeout))
    2341
    2442    def get(self, key, default=None):
    2543        val = self._cache.get(smart_str(key))
     
    3452    def set(self, key, value, timeout=0):
    3553        if isinstance(value, unicode):
    3654            value = value.encode('utf-8')
    37         self._cache.set(smart_str(key), value, timeout or self.default_timeout)
     55        self._cache.set(smart_str(key), value, self._get_memcache_timeout(timeout))
    3856
    3957    def delete(self, key):
    4058        self._cache.delete(smart_str(key))
  • tests/regressiontests/cache/tests.py

     
    347347        def setUp(self):
    348348            self.cache = get_cache(settings.CACHE_BACKEND)
    349349
     350        def test_long_timeout(self):
     351            '''
     352            Using a timeout greater than 30 days makes memcached think
     353            it is an absolute expiration timestamp instead of a relative
     354            offset. Test that we honour this convention. Refs #12399.
     355            '''
     356            self.cache.set('key1', 'eggs', 60*60*24*30 + 1) #30 days + 1 second
     357            self.assert_('key1' in self.cache)
     358           
    350359class FileBasedCacheTests(unittest.TestCase, BaseCacheTests):
    351360    """
    352361    Specific test cases for the file-based cache.
Back to Top