Prevented initialization of unused database connections.

This commit is contained in:
Florian Apolloner 2022-03-08 11:48:56 +01:00 committed by Mariusz Felisiak
parent 13378ad952
commit 4f92cf87b0
8 changed files with 20 additions and 22 deletions

View File

@ -51,7 +51,7 @@ class PostgresConfig(AppConfig):
def ready(self):
setting_changed.connect(uninstall_if_needed)
# Connections may already exist before we are called.
for conn in connections.all():
for conn in connections.all(initialized_only=True):
if conn.vendor == "postgresql":
conn.introspection.data_types_reverse.update(
{

View File

@ -51,14 +51,6 @@ class CacheHandler(BaseConnectionHandler):
) from e
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()

View File

@ -344,16 +344,13 @@ class BaseHandler:
def make_view_atomic(self, view):
non_atomic_requests = getattr(view, "_non_atomic_requests", set())
for db in connections.all():
if (
db.settings_dict["ATOMIC_REQUESTS"]
and db.alias not in non_atomic_requests
):
for alias, settings_dict in connections.settings.items():
if settings_dict["ATOMIC_REQUESTS"] and alias not in non_atomic_requests:
if asyncio.iscoroutinefunction(view):
raise RuntimeError(
"You cannot use ATOMIC_REQUESTS with async views."
)
view = transaction.atomic(using=db.alias)(view)
view = transaction.atomic(using=alias)(view)
return view
def process_exception_by_middleware(self, exception, request):

View File

@ -43,7 +43,7 @@ connection = ConnectionProxy(connections, DEFAULT_DB_ALIAS)
# Register an event to reset saved queries when a Django request is started.
def reset_queries(**kwargs):
for conn in connections.all():
for conn in connections.all(initialized_only=True):
conn.queries_log.clear()
@ -53,7 +53,7 @@ signals.request_started.connect(reset_queries)
# Register an event to reset transaction state and close connections past
# their lifetime.
def close_old_connections(**kwargs):
for conn in connections.all():
for conn in connections.all(initialized_only=True):
conn.close_if_unusable_or_obsolete()

View File

@ -70,7 +70,7 @@ def update_connections_time_zone(*, setting, **kwargs):
# Reset the database connections' time zone
if setting in {"TIME_ZONE", "USE_TZ"}:
for conn in connections.all():
for conn in connections.all(initialized_only=True):
try:
del conn.timezone
except AttributeError:

View File

@ -1197,7 +1197,7 @@ class TransactionTestCase(SimpleTestCase):
# tests (e.g., losing a timezone setting causing objects to be
# created with the wrong time). To make sure this doesn't
# happen, get a clean connection at the start of every test.
for conn in connections.all():
for conn in connections.all(initialized_only=True):
conn.close()
finally:
if self.available_apps is not None:
@ -1378,7 +1378,7 @@ class TestCase(TransactionTestCase):
def tearDownClass(cls):
if cls._databases_support_transactions():
cls._rollback_atomics(cls.cls_atomics)
for conn in connections.all():
for conn in connections.all(initialized_only=True):
conn.close()
super().tearDownClass()

View File

@ -72,5 +72,10 @@ class BaseConnectionHandler:
def __iter__(self):
return iter(self.settings)
def all(self):
return [self[alias] for alias in self]
def all(self, initialized_only=False):
return [
self[alias]
for alias in self
# If initialized_only is True, return only initialized connections.
if not initialized_only or hasattr(self._connections, alias)
]

View File

@ -8,3 +8,7 @@ class BaseConnectionHandlerTests(SimpleTestCase):
msg = "Subclasses must implement create_connection()."
with self.assertRaisesMessage(NotImplementedError, msg):
handler.create_connection(None)
def test_all_initialized_only(self):
handler = BaseConnectionHandler({"default": {}})
self.assertEqual(handler.all(initialized_only=True), [])