Skip to content

Instantly share code, notes, and snippets.

@raphaelm
Created December 20, 2022 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raphaelm/300a72784e78f922b8d33d83855652b6 to your computer and use it in GitHub Desktop.
Save raphaelm/300a72784e78f922b8d33d83855652b6 to your computer and use it in GitHub Desktop.
Database connection pool when using eventlet
from django.core import signals
from django.db import connections
from django.db.utils import ConnectionHandler
from eventlet.pools import Pool
_unpatched_get_item = ConnectionHandler.__getitem__
class ConnectionPool(Pool):
def __init__(self, alias, max_size=4):
super().__init__(min_size=0, max_size=max_size, order_as_stack=False)
self._alias = alias
def create(self):
conn = _unpatched_get_item(connections, self._alias)
conn.inc_thread_sharing()
return conn
def _patched_get_item(self, alias):
# simple reuse within single request
if hasattr(self._connections, alias):
return getattr(self._connections, alias)
# get a connection from the connection pool and bind it to the green thread
if not hasattr(ConnectionHandler, 'connection_pool'):
ConnectionHandler.connection_pool = {}
if alias not in self.connection_pool:
self.connection_pool[alias] = ConnectionPool(alias, max_size=4)
conn = self.connection_pool[alias].get()
conn.close_if_unusable_or_obsolete()
setattr(self._connections, alias, conn)
return conn
def put_connection_back_in_pool(sender, **kwargs):
aliases = []
for alias in connections:
aliases.append(alias)
conn = connections[alias]
ConnectionHandler.connection_pool[alias].put(conn)
for alias in aliases:
del connections[alias]
def patch_connection_handler():
signals.request_finished.connect(put_connection_back_in_pool)
ConnectionHandler.__getitem__ = _patched_get_item
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment