Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Properly closed cache connections at the end of the request.

This only affects the new cache api and not the deprecated get_cache.

Refs #21012
  • Loading branch information...
commit d47f794f8fa05591632b8cad4b134858e7ae140d 1 parent 8adbfdf
@apollo13 apollo13 authored
Showing with 41 additions and 11 deletions.
  1. +22 −10 django/core/cache/__init__.py
  2. +19 −1 tests/cache/tests.py
View
32 django/core/cache/__init__.py
@@ -53,7 +53,12 @@ def get_cache(backend, **kwargs):
"""
warnings.warn("'get_cache' is deprecated in favor of 'caches'.",
PendingDeprecationWarning, stacklevel=2)
- return _create_cache(backend, **kwargs)
+ cache = _create_cache(backend, **kwargs)
+ # Some caches -- python-memcached in particular -- need to do a cleanup at the
+ # end of a request cycle. If not implemented in a particular backend
+ # cache.close is a no-op
+ signals.request_finished.connect(cache.close)
+ return cache
def _create_cache(backend, **kwargs):
@@ -79,12 +84,7 @@ def _create_cache(backend, **kwargs):
except (AttributeError, ImportError, ImproperlyConfigured) as e:
raise InvalidCacheBackendError(
"Could not find backend '%s': %s" % (backend, e))
- cache = backend_cls(location, params)
- # Some caches -- python-memcached in particular -- need to do a cleanup at the
- # end of a request cycle. If not implemented in a particular backend
- # cache.close is a no-op
- signals.request_finished.connect(cache.close)
- return cache
+ return backend_cls(location, params)
class CacheHandler(object):
@@ -98,8 +98,10 @@ def __init__(self):
def __getitem__(self, alias):
try:
- return getattr(self._caches, alias)
+ return self._caches.caches[alias]
except AttributeError:
+ self._caches.caches = {}
+ except KeyError:
pass
if alias not in settings.CACHES:
@@ -108,10 +110,12 @@ def __getitem__(self, alias):
)
cache = _create_cache(alias)
- setattr(self._caches, alias, cache)
-
+ self._caches.caches[alias] = cache
return cache
+ def all(self):
+ return getattr(self._caches, 'caches', {}).values()
+
caches = CacheHandler()
@@ -141,3 +145,11 @@ def __ne__(self, other):
return caches[DEFAULT_CACHE_ALIAS] != other
cache = DefaultCacheProxy()
+
+def close_caches(**kwargs):
+ # Some caches -- python-memcached in particular -- need to do a cleanup at the
+ # end of a request cycle. If not implemented in a particular backend
+ # cache.close is a no-op
+ for cache in caches.all():
+ cache.close()
+signals.request_finished.connect(close_caches)
View
20 tests/cache/tests.py
@@ -203,7 +203,6 @@ def custom_key_func(key, key_prefix, version):
'custom_key2': {'KEY_FUNCTION': 'cache.tests.custom_key_func'},
'cull': {'OPTIONS': {'MAX_ENTRIES': 30}},
'zero_cull': {'OPTIONS': {'CULL_FREQUENCY': 0, 'MAX_ENTRIES': 30}},
- 'other': {'LOCATION': 'other'},
}
@@ -1014,6 +1013,13 @@ def setUp(self):
caches['custom_key2']._cache = cache._cache
caches['custom_key2']._expire_info = cache._expire_info
+ @override_settings(CACHES={
+ 'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'},
+ 'other': {
+ 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
+ 'LOCATION': 'other'
+ },
+ })
def test_multiple_caches(self):
"Check that multiple locmem caches are isolated"
cache.set('value', 42)
@@ -1139,6 +1145,12 @@ def test_custom_key_validation(self):
self.assertEqual(cache.get(key), val)
+@override_settings(
+ CACHES={
+ 'default': {
+ 'BACKEND': 'cache.closeable_cache.CacheClass',
+ }
+ },)
class GetCacheTests(IgnorePendingDeprecationWarningsMixin, TestCase):
def test_simple(self):
@@ -1157,6 +1169,12 @@ def test_simple(self):
self.assertRaises(InvalidCacheBackendError, get_cache, 'does_not_exist')
def test_close(self):
+ from django.core import signals
+ self.assertFalse(cache.closed)
+ signals.request_finished.send(self.__class__)
+ self.assertTrue(cache.closed)
+
+ def test_close_deprecated(self):
from django.core.cache import get_cache
from django.core import signals
cache = get_cache('cache.closeable_cache.CacheClass')
Please sign in to comment.
Something went wrong with that request. Please try again.