Usiłowałem znaleźć naprawdę szczegółowe informacje na temat działania ThreadedConnectionPool. https://bbengfort.github.io/observations/2017/12/06/psycopg2-transactions.html nie jest zły, ale okazuje się, że jego twierdzenie, że getconn blokuje się, dopóki połączenie nie stanie się dostępne, jest niepoprawne. Sprawdzając kod, wszystko, co dodaje ThreadedConnectionPool, jest blokadą wokół metod AbstractConnectionPool, aby zapobiec sytuacji wyścigu. Jeśli w dowolnym momencie próbuje się użyć więcej niż maxconn połączeń, pula połączeń zostanie wyczerpana PoolError zostanie podniesiony.
Jeśli chcesz czegoś prostszego niż zaakceptowana odpowiedź, dalsze zawijanie metod w semafor zapewniający blokowanie do momentu, gdy połączenie stanie się dostępne, powinno wystarczyć:
from psycopg2.pool import ThreadedConnectionPool
from threading import Semaphore
class ReallyThreadedConnectionPool(ThreadedConnectionPool):
def __init__(self, minconn, maxconn, *args, **kwargs):
self._semaphore = Semaphore(maxconn)
super().__init__(minconn, maxconn, *args, **kwargs)
def getconn(self, *args, **kwargs):
self._semaphore.acquire()
return super().getconn(*args, **kwargs)
def putconn(self, *args, **kwargs):
super().putconn(*args, **kwargs)
self._semaphore.release()