django32: change the way Thread are made tenant aware (#67760)
gitea-wip/hobo/pipeline/pr-main This commit looks good Details

Django 3.2. changed the implementation of django.db.ConnectionHandler it
now uses asgiref.local.Local as a thread/asyncio-task local dictionnary
instead of threading.local. This new implementation use
threading.current_thread() to get a reference to the current thread
instead of threading._get_ident(), but inside __bootstrap_inner, the
_active dictionnary is not initialized and current_thread() returns a
dummy value instead of the current thread.

To work around this behaviour I made __bootstrap_inner wrap the run
method with the code needed to setup the tenant, so that it's run after
__boostrap_inner initialization of the current thread in the _active
dictionnary.
This commit is contained in:
Benjamin Dauvergne 2023-01-18 11:57:15 +01:00
parent 9bc96520ac
commit 842f699e8a
1 changed files with 28 additions and 14 deletions

View File

@ -14,6 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import functools
import threading
_Thread_start = threading.Thread.start
@ -28,21 +29,34 @@ def _new_start(self):
return _Thread_start(self)
def wrap_run(self, func):
if getattr(func, '_wrapped', False):
return func
@functools.wraps(func)
def wrapper():
tenant = getattr(self, 'tenant', None)
if tenant is not None:
from django.db import connection
old_tenant = connection.tenant
connection.set_tenant(self.tenant)
try:
func()
finally:
connection.set_tenant(old_tenant)
connection.close()
else:
func()
wrapper._wrapped = True
return wrapper
def _new__bootstrap_inner(self):
tenant = getattr(self, 'tenant', None)
if tenant is not None:
from django.db import connection
old_tenant = connection.tenant
connection.set_tenant(self.tenant)
try:
_Thread__bootstrap_inner(self)
finally:
connection.set_tenant(old_tenant)
connection.close()
else:
_Thread__bootstrap_inner(self)
self.run = wrap_run(self, self.run)
_Thread__bootstrap_inner(self)
def install_tenant_aware_threads():