Fixed #32747 -- Prevented initialization of unused caches.

Thanks Alexander Ebral for the report.

Regression in 98e05ccde4.
This commit is contained in:
Mariusz Felisiak 2021-05-14 11:53:17 +02:00
parent a24fed399c
commit 958cdf65ae
3 changed files with 41 additions and 1 deletions

View File

@ -43,6 +43,13 @@ class CacheHandler(BaseConnectionHandler):
) from e ) from e
return backend_cls(location, params) return backend_cls(location, params)
def all(self, initialized_only=False):
return [
self[alias] for alias in self
# If initialized_only is True, return only initialized caches.
if not initialized_only or hasattr(self._connections, alias)
]
caches = CacheHandler() caches = CacheHandler()
@ -52,7 +59,7 @@ cache = ConnectionProxy(caches, DEFAULT_CACHE_ALIAS)
def close_caches(**kwargs): def close_caches(**kwargs):
# Some caches need to do a cleanup at the end of a request cycle. If not # Some caches 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. # implemented in a particular backend cache.close() is a no-op.
for cache in caches.all(): for cache in caches.all(initialized_only=True):
cache.close() cache.close()

View File

@ -15,3 +15,6 @@ Bugfixes
* Fixed a bug in Django 3.2 where a system check would crash on an abstract * Fixed a bug in Django 3.2 where a system check would crash on an abstract
model (:ticket:`32733`). model (:ticket:`32733`).
* Prevented unnecessary initialization of unused caches following a regression
in Django 3.2 (:ticket:`32747`).

30
tests/cache/tests.py vendored
View File

@ -1723,6 +1723,19 @@ class CacheClosingTests(SimpleTestCase):
signals.request_finished.send(self.__class__) signals.request_finished.send(self.__class__)
self.assertTrue(cache.closed) self.assertTrue(cache.closed)
def test_close_only_initialized(self):
with self.settings(CACHES={
'cache_1': {
'BACKEND': 'cache.closeable_cache.CacheClass',
},
'cache_2': {
'BACKEND': 'cache.closeable_cache.CacheClass',
},
}):
self.assertEqual(caches.all(initialized_only=True), [])
signals.request_finished.send(self.__class__)
self.assertEqual(caches.all(initialized_only=True), [])
DEFAULT_MEMORY_CACHES_SETTINGS = { DEFAULT_MEMORY_CACHES_SETTINGS = {
'default': { 'default': {
@ -2625,3 +2638,20 @@ class CacheHandlerTest(SimpleTestCase):
) )
with self.assertRaisesMessage(InvalidCacheBackendError, msg): with self.assertRaisesMessage(InvalidCacheBackendError, msg):
test_caches['invalid_backend'] test_caches['invalid_backend']
def test_all(self):
test_caches = CacheHandler({
'cache_1': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
},
'cache_2': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
},
})
self.assertEqual(test_caches.all(initialized_only=True), [])
cache_1 = test_caches['cache_1']
self.assertEqual(test_caches.all(initialized_only=True), [cache_1])
self.assertEqual(len(test_caches.all()), 2)
# .all() initializes all caches.
self.assertEqual(len(test_caches.all(initialized_only=True)), 2)
self.assertEqual(test_caches.all(), test_caches.all(initialized_only=True))