Loading django/core/cache/backends/memcached.py +3 −1 Original line number Diff line number Diff line Loading @@ -86,7 +86,9 @@ class BaseMemcachedCache(six.with_metaclass(BaseMemcachedCacheMethods, BaseCache def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): key = self.make_key(key, version=version) self._cache.set(key, value, self.get_backend_timeout(timeout)) if not self._cache.set(key, value, self.get_backend_timeout(timeout)): # make sure the key doesn't keep its old value in case of failure to set (memcached's 1MB limit) self._cache.delete(key) def delete(self, key, version=None): key = self.make_key(key, version=version) Loading docs/releases/1.8.txt +4 −0 Original line number Diff line number Diff line Loading @@ -729,6 +729,10 @@ Miscellaneous .. _universal newlines: http://www.python.org/dev/peps/pep-0278 * The Memcached cache backends ``MemcachedCache`` and ``PyLibMCCache`` will delete a key if ``set()`` fails. This is necessary to ensure the ``cache_db`` session store always fetches the most current session data. .. _deprecated-features-1.8: Features deprecated in 1.8 Loading tests/cache/tests.py +18 −0 Original line number Diff line number Diff line Loading @@ -1133,6 +1133,24 @@ class MemcachedCacheTests(BaseCacheTests, TestCase): # culling isn't implemented, memcached deals with it. pass def test_memcached_deletes_key_on_failed_set(self): # By default memcached allows objects up to 1MB. For the cache_db session # backend to always use the current session, memcached needs to delete # the old key if it fails to set. # pylibmc doesn't seem to have SERVER_MAX_VALUE_LENGTH as far as I can # tell from a quick check of its source code. This is falling back to # the default value exposed by python-memcached on my system. max_value_length = getattr(cache._lib, 'SERVER_MAX_VALUE_LENGTH', 1048576) cache.set('small_value', 'a') self.assertEqual(cache.get('small_value'), 'a') large_value = 'a' * (max_value_length + 1) cache.set('small_value', large_value) # small_value should be deleted, or set if configured to accept larger values value = cache.get('small_value') self.assertTrue(value is None or value == large_value) @override_settings(CACHES=caches_setting_for_tests( BACKEND='django.core.cache.backends.filebased.FileBasedCache', Loading Loading
django/core/cache/backends/memcached.py +3 −1 Original line number Diff line number Diff line Loading @@ -86,7 +86,9 @@ class BaseMemcachedCache(six.with_metaclass(BaseMemcachedCacheMethods, BaseCache def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): key = self.make_key(key, version=version) self._cache.set(key, value, self.get_backend_timeout(timeout)) if not self._cache.set(key, value, self.get_backend_timeout(timeout)): # make sure the key doesn't keep its old value in case of failure to set (memcached's 1MB limit) self._cache.delete(key) def delete(self, key, version=None): key = self.make_key(key, version=version) Loading
docs/releases/1.8.txt +4 −0 Original line number Diff line number Diff line Loading @@ -729,6 +729,10 @@ Miscellaneous .. _universal newlines: http://www.python.org/dev/peps/pep-0278 * The Memcached cache backends ``MemcachedCache`` and ``PyLibMCCache`` will delete a key if ``set()`` fails. This is necessary to ensure the ``cache_db`` session store always fetches the most current session data. .. _deprecated-features-1.8: Features deprecated in 1.8 Loading
tests/cache/tests.py +18 −0 Original line number Diff line number Diff line Loading @@ -1133,6 +1133,24 @@ class MemcachedCacheTests(BaseCacheTests, TestCase): # culling isn't implemented, memcached deals with it. pass def test_memcached_deletes_key_on_failed_set(self): # By default memcached allows objects up to 1MB. For the cache_db session # backend to always use the current session, memcached needs to delete # the old key if it fails to set. # pylibmc doesn't seem to have SERVER_MAX_VALUE_LENGTH as far as I can # tell from a quick check of its source code. This is falling back to # the default value exposed by python-memcached on my system. max_value_length = getattr(cache._lib, 'SERVER_MAX_VALUE_LENGTH', 1048576) cache.set('small_value', 'a') self.assertEqual(cache.get('small_value'), 'a') large_value = 'a' * (max_value_length + 1) cache.set('small_value', large_value) # small_value should be deleted, or set if configured to accept larger values value = cache.get('small_value') self.assertTrue(value is None or value == large_value) @override_settings(CACHES=caches_setting_for_tests( BACKEND='django.core.cache.backends.filebased.FileBasedCache', Loading