mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Prevented initialization of unused database connections.
This commit is contained in:
		
				
					committed by
					
						
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							13378ad952
						
					
				
				
					commit
					4f92cf87b0
				
			@@ -51,7 +51,7 @@ class PostgresConfig(AppConfig):
 | 
				
			|||||||
    def ready(self):
 | 
					    def ready(self):
 | 
				
			||||||
        setting_changed.connect(uninstall_if_needed)
 | 
					        setting_changed.connect(uninstall_if_needed)
 | 
				
			||||||
        # Connections may already exist before we are called.
 | 
					        # 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":
 | 
					            if conn.vendor == "postgresql":
 | 
				
			||||||
                conn.introspection.data_types_reverse.update(
 | 
					                conn.introspection.data_types_reverse.update(
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								django/core/cache/__init__.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								django/core/cache/__init__.py
									
									
									
									
										vendored
									
									
								
							@@ -51,14 +51,6 @@ 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()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -344,16 +344,13 @@ class BaseHandler:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def make_view_atomic(self, view):
 | 
					    def make_view_atomic(self, view):
 | 
				
			||||||
        non_atomic_requests = getattr(view, "_non_atomic_requests", set())
 | 
					        non_atomic_requests = getattr(view, "_non_atomic_requests", set())
 | 
				
			||||||
        for db in connections.all():
 | 
					        for alias, settings_dict in connections.settings.items():
 | 
				
			||||||
            if (
 | 
					            if settings_dict["ATOMIC_REQUESTS"] and alias not in non_atomic_requests:
 | 
				
			||||||
                db.settings_dict["ATOMIC_REQUESTS"]
 | 
					 | 
				
			||||||
                and db.alias not in non_atomic_requests
 | 
					 | 
				
			||||||
            ):
 | 
					 | 
				
			||||||
                if asyncio.iscoroutinefunction(view):
 | 
					                if asyncio.iscoroutinefunction(view):
 | 
				
			||||||
                    raise RuntimeError(
 | 
					                    raise RuntimeError(
 | 
				
			||||||
                        "You cannot use ATOMIC_REQUESTS with async views."
 | 
					                        "You cannot use ATOMIC_REQUESTS with async views."
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                view = transaction.atomic(using=db.alias)(view)
 | 
					                view = transaction.atomic(using=alias)(view)
 | 
				
			||||||
        return view
 | 
					        return view
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def process_exception_by_middleware(self, exception, request):
 | 
					    def process_exception_by_middleware(self, exception, request):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,7 @@ connection = ConnectionProxy(connections, DEFAULT_DB_ALIAS)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Register an event to reset saved queries when a Django request is started.
 | 
					# Register an event to reset saved queries when a Django request is started.
 | 
				
			||||||
def reset_queries(**kwargs):
 | 
					def reset_queries(**kwargs):
 | 
				
			||||||
    for conn in connections.all():
 | 
					    for conn in connections.all(initialized_only=True):
 | 
				
			||||||
        conn.queries_log.clear()
 | 
					        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
 | 
					# Register an event to reset transaction state and close connections past
 | 
				
			||||||
# their lifetime.
 | 
					# their lifetime.
 | 
				
			||||||
def close_old_connections(**kwargs):
 | 
					def close_old_connections(**kwargs):
 | 
				
			||||||
    for conn in connections.all():
 | 
					    for conn in connections.all(initialized_only=True):
 | 
				
			||||||
        conn.close_if_unusable_or_obsolete()
 | 
					        conn.close_if_unusable_or_obsolete()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,7 +70,7 @@ def update_connections_time_zone(*, setting, **kwargs):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    # Reset the database connections' time zone
 | 
					    # Reset the database connections' time zone
 | 
				
			||||||
    if setting in {"TIME_ZONE", "USE_TZ"}:
 | 
					    if setting in {"TIME_ZONE", "USE_TZ"}:
 | 
				
			||||||
        for conn in connections.all():
 | 
					        for conn in connections.all(initialized_only=True):
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                del conn.timezone
 | 
					                del conn.timezone
 | 
				
			||||||
            except AttributeError:
 | 
					            except AttributeError:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1197,7 +1197,7 @@ class TransactionTestCase(SimpleTestCase):
 | 
				
			|||||||
                # tests (e.g., losing a timezone setting causing objects to be
 | 
					                # tests (e.g., losing a timezone setting causing objects to be
 | 
				
			||||||
                # created with the wrong time). To make sure this doesn't
 | 
					                # created with the wrong time). To make sure this doesn't
 | 
				
			||||||
                # happen, get a clean connection at the start of every test.
 | 
					                # 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()
 | 
					                    conn.close()
 | 
				
			||||||
        finally:
 | 
					        finally:
 | 
				
			||||||
            if self.available_apps is not None:
 | 
					            if self.available_apps is not None:
 | 
				
			||||||
@@ -1378,7 +1378,7 @@ class TestCase(TransactionTestCase):
 | 
				
			|||||||
    def tearDownClass(cls):
 | 
					    def tearDownClass(cls):
 | 
				
			||||||
        if cls._databases_support_transactions():
 | 
					        if cls._databases_support_transactions():
 | 
				
			||||||
            cls._rollback_atomics(cls.cls_atomics)
 | 
					            cls._rollback_atomics(cls.cls_atomics)
 | 
				
			||||||
            for conn in connections.all():
 | 
					            for conn in connections.all(initialized_only=True):
 | 
				
			||||||
                conn.close()
 | 
					                conn.close()
 | 
				
			||||||
        super().tearDownClass()
 | 
					        super().tearDownClass()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,5 +72,10 @@ class BaseConnectionHandler:
 | 
				
			|||||||
    def __iter__(self):
 | 
					    def __iter__(self):
 | 
				
			||||||
        return iter(self.settings)
 | 
					        return iter(self.settings)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def all(self):
 | 
					    def all(self, initialized_only=False):
 | 
				
			||||||
        return [self[alias] for alias in self]
 | 
					        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)
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,3 +8,7 @@ class BaseConnectionHandlerTests(SimpleTestCase):
 | 
				
			|||||||
        msg = "Subclasses must implement create_connection()."
 | 
					        msg = "Subclasses must implement create_connection()."
 | 
				
			||||||
        with self.assertRaisesMessage(NotImplementedError, msg):
 | 
					        with self.assertRaisesMessage(NotImplementedError, msg):
 | 
				
			||||||
            handler.create_connection(None)
 | 
					            handler.create_connection(None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_all_initialized_only(self):
 | 
				
			||||||
 | 
					        handler = BaseConnectionHandler({"default": {}})
 | 
				
			||||||
 | 
					        self.assertEqual(handler.all(initialized_only=True), [])
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user