I have a long running Python process which uses the Django ORM. It looks something like this:
import django
from django.db import connection
from my_app import models
def my_process():
django.setup()
while (True):
do_stuff()
connection.close()
models.MyDjangoModel().save()
Sometimes do_stuff
takes a really long time, at which point I was running into an error where my MySql connection timed out because the database server killed the connection as idle. Adding the connection.close()
line forces django to get a new connection every time and fixes that issue. (See https://code.djangoproject.com/ticket/21597).
However, I am testing this process using a django.test.TestCase
, and calling connection.close
causes those tests to fail, as django's TestCase
class wraps the test in a transaction, and closing the connection within that transaction causes the transaction to break and raises a django.db.transaction.TransactionManagementError
.
One attempt at resolving this issue I tried is setting the CONN_MAX_AGE
database parameter and calling connection.close_if_unusable_or_obsolete
instead, but the transaction also changes the connection's autocommit
setting from the settings' default value of True
to False
which in turn causes close_if_unusable_or_obsolete
to try and close the connection anyway (https://github.com/django/django/blob/master/django/db/backends/base/base.py#L497).
I guess I could also mock connection.close
in test so it does nothing, but that seems kind of hacky.
What is the best way to test a django method which needs to close the database connection?