For a long time I have been running into problems with Django connection errors when running a database query after a long idle period. This does not affect website per-se because connections last a very short time but for batch processes where there is a long interval between database access, Django does not detect that database has dropped the connection and raises an error.
Which really should not be happening because my database connection settings includes:
'CONN_MAX_AGE': 3500, # 3500 seconds because wait_timeout = 3600 in my.cnf
telling Django that the maximum age of the connection should be 3500 seconds, and the timeout in mysql is set to 3600.
I was hoping that this was going to be fixed with Django 4.2 with this new setting:
'CONN_HEALTH_CHECKS': True, # Health check connections
but no change.
I had been dealing with the issue by inserting this before accessing the database:
connections.close_all()
but this is inelegant.
So I cooked up a decorator and a function to ensure that database connections were all good before database access, here is the function:
from django.db import connections
def ensureDatabaseConnections(reconnect=True):
# Process all connections
for _connection in connections.all():
# The 'is_usable' method only exists if the connection was made
if _connection.connection and not _connection.is_usable():
_connection.close()
if reconnect:
_connection.connect()
And here is the decorator:
from django.db import connections
def ensureDatabaseConnections(function, reconnect=True):
# Wrapper
def wrapper(reconnect=True, **kwargs):
# Process all connections
for _connection in connections.all():
# The 'is_usable' method only exists if the connection was made
if _connection.connection and not _connection.is_usable():
_connection.close()
if reconnect:
_connection.connect()
# Return the wrapped function
return function(*args, **kwargs)
# Return the wrapper
return wrapper