Ticket #17258: 17258.thread-local-connections.2.diff

File 17258.thread-local-connections.2.diff, 6.0 KB (added by Julien Phalip, 8 years ago)
  • django/db/__init__.py

    diff --git a/django/db/__init__.py b/django/db/__init__.py
    index 8395468..d589338 100644
    a b  
     1from threading import local
    12from django.conf import settings
    23from django.core import signals
    34from django.core.exceptions import ImproperlyConfigured
    router = ConnectionRouter(settings.DATABASE_ROUTERS) 
    2223# we manually create the dictionary from the settings, passing only the
    2324# settings that the database backends care about. Note that TIME_ZONE is used
    2425# by the PostgreSQL backends.
    25 # we load all these up for backwards compatibility, you should use
     26# We load all these up for backwards compatibility, you should use
    2627# connections['default'] instead.
    27 connection = connections[DEFAULT_DB_ALIAS]
     28class DefaultConnectionProxy(object):
     29    """
     30    Proxy for the thread-local default connection.
     31    """
     32    def __getattr__(self, item):
     33        return getattr(connections[DEFAULT_DB_ALIAS], item)
     34
     35    def __setattr__(self, name, value):
     36        return setattr(connections[DEFAULT_DB_ALIAS], name, value)
     37
     38connection = DefaultConnectionProxy()
    2839backend = load_backend(connection.settings_dict['ENGINE'])
    2940
    3041# Register an event that closes the database connection
  • django/db/backends/__init__.py

    diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
    index f2bde84..0f4fc31 100644
    a b try: 
    22    import thread
    33except ImportError:
    44    import dummy_thread as thread
    5 from threading import local
    65from contextlib import contextmanager
    76
    87from django.conf import settings
    from django.utils.importlib import import_module 
    1312from django.utils.timezone import is_aware
    1413
    1514
    16 class BaseDatabaseWrapper(local):
     15class BaseDatabaseWrapper(object):
    1716    """
    1817    Represents a database connection.
    1918    """
  • django/db/utils.py

    diff --git a/django/db/utils.py b/django/db/utils.py
    index f0c13e3..41ad6df 100644
    a b  
    11import os
     2from threading import local
    23
    34from django.conf import settings
    45from django.core.exceptions import ImproperlyConfigured
    class ConnectionDoesNotExist(Exception): 
    5051class ConnectionHandler(object):
    5152    def __init__(self, databases):
    5253        self.databases = databases
    53         self._connections = {}
     54        self._connections = local()
    5455
    5556    def ensure_defaults(self, alias):
    5657        """
    class ConnectionHandler(object): 
    7374            conn.setdefault(setting, None)
    7475
    7576    def __getitem__(self, alias):
    76         if alias in self._connections:
    77             return self._connections[alias]
     77        if hasattr(self._connections, alias):
     78            return getattr(self._connections, alias)
    7879
    7980        self.ensure_defaults(alias)
    8081        db = self.databases[alias]
    8182        backend = load_backend(db['ENGINE'])
    8283        conn = backend.DatabaseWrapper(db, alias)
    83         self._connections[alias] = conn
     84        setattr(self._connections, alias, conn)
    8485        return conn
    8586
     87    def __setitem__(self, key, value):
     88        setattr(self._connections, key, value)
     89
    8690    def __iter__(self):
    8791        return iter(self.databases)
    8892
  • tests/regressiontests/backends/tests.py

    diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py
    index 936f010..e569df9 100644
    a b  
    33from __future__ import with_statement, absolute_import
    44
    55import datetime
     6import threading
    67
    78from django.conf import settings
    89from django.core.management.color import no_style
    class ConnectionCreatedSignalTest(TestCase): 
    283284        connection_created.connect(receiver)
    284285        connection.close()
    285286        cursor = connection.cursor()
    286         self.assertTrue(data["connection"] is connection)
     287        self.assertTrue(data["connection"].connection is connection.connection)
    287288
    288289        connection_created.disconnect(receiver)
    289290        data.clear()
    class FkConstraintsTests(TransactionTestCase): 
    446447                        connection.check_constraints()
    447448            finally:
    448449                transaction.rollback()
     450
     451class ThreadTests(TestCase):
     452
     453    def test_default_connection_thread_local(self):
     454        """
     455        Ensure that the default connection (i.e. django.db.connection) is
     456        different for each thread.
     457        Refs #17258.
     458        """
     459        connections_set = set()
     460        connection.cursor()
     461        connections_set.add(connection.connection)
     462        def runner():
     463            from django.db import connection
     464            connection.cursor()
     465            connections_set.add(connection.connection)
     466        for x in xrange(2):
     467            t = threading.Thread(target=runner)
     468            t.start()
     469            t.join()
     470        self.assertEquals(len(connections_set), 3)
     471        # Finish by closing the connections opened by the other threads (the
     472        # connection opened in the main thread will automatically be closed on
     473        # teardown).
     474        for conn in connections_set:
     475            if conn != connection.connection:
     476                conn.close()
     477
     478    def test_connections_thread_local(self):
     479        """
     480        Ensure that the connections are different for each thread.
     481        Refs #17258.
     482        """
     483        connections_set = set()
     484        for conn in connections.all():
     485            connections_set.add(conn)
     486        def runner():
     487            from django.db import connections
     488            for conn in connections.all():
     489                connections_set.add(conn)
     490        for x in xrange(2):
     491            t = threading.Thread(target=runner)
     492            t.start()
     493            t.join()
     494        self.assertEquals(len(connections_set), 6)
     495        # Finish by closing the connections opened by the other threads (the
     496        # connection opened in the main thread will automatically be closed on
     497        # teardown).
     498        for conn in connections_set:
     499            if conn != connection:
     500                conn.close()
     501 No newline at end of file
Back to Top