PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Django ORM membocorkan koneksi saat menggunakan ThreadPoolExecutor

Dugaan saya adalah bahwa ThreadPoolExecutor bukan yang membuat koneksi DB, tetapi pekerjaan berulir adalah yang menahan koneksi. Saya sudah harus berurusan dengan ini.

Saya akhirnya membuat pembungkus ini, untuk memastikan bahwa utas ditutup secara manual setiap kali pekerjaan dilakukan di ThreadPoolExecutor. Ini akan berguna untuk memastikan koneksi tidak bocor, sejauh ini saya belum melihat adanya kebocoran saat menggunakan kode ini.

from functools import wraps
from concurrent.futures import ThreadPoolExecutor
from django.db import connection

class DjangoConnectionThreadPoolExecutor(ThreadPoolExecutor):
    """
    When a function is passed into the ThreadPoolExecutor via either submit() or map(), 
    this will wrap the function, and make sure that close_django_db_connection() is called 
    inside the thread when it's finished so Django doesn't leak DB connections.

    Since map() calls submit(), only submit() needs to be overwritten.
    """
    def close_django_db_connection(self):
        connection.close()

    def generate_thread_closing_wrapper(self, fn):
        @wraps(fn)
        def new_func(*args, **kwargs):
            try:
                return fn(*args, **kwargs)
            finally:
                self.close_django_db_connection()
        return new_func

    def submit(*args, **kwargs):
        """
        I took the args filtering/unpacking logic from 
   
        https://github.com/python/cpython/blob/3.7/Lib/concurrent/futures/thread.py 
        
        so I can properly get the function object the same way it was done there.
        """
        if len(args) >= 2:
            self, fn, *args = args
            fn = self.generate_thread_closing_wrapper(fn=fn)
        elif not args:
            raise TypeError("descriptor 'submit' of 'ThreadPoolExecutor' object "
                        "needs an argument")
        elif 'fn' in kwargs:
            fn = self.generate_thread_closing_wrapper(fn=kwargs.pop('fn'))
            self, *args = args
    
        return super(self.__class__, self).submit(fn, *args, **kwargs)

Maka Anda bisa menggunakan ini:

    with DjangoConnectionThreadPoolExecutor(max_workers=15) as executor:
        results = list(executor.map(func, args_list))

...dan yakinlah bahwa koneksi akan ditutup.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara mengurutkan hasil dari string_agg()

  2. Cara menggunakan pencarian PreparedStatement dan Case INsensitive

  3. Npgsql:Representasi floating point lama untuk cap waktu tidak didukung

  4. Memesan urutan numerik yang dibatasi titik (misalnya, nomor versi)

  5. Menghapus Baris Duplikat di PostgreSQL dengan banyak kolom