У меня есть длительный процесс Python, который использует Django ORM. Это выглядит примерно так:
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()
Иногда do_stuff
занимает очень много времени, и в этот момент я столкнулся с ошибкой, когда время ожидания моего соединения MySql истекло, потому что сервер базы данных прервал соединение как бездействующее. Добавление строки connection.close()
заставляет django каждый раз получать новое соединение и устраняет эту проблему. (См. https://code.djangoproject.com/ticket/21597).
Однако я тестирую этот процесс, используя django.test.TestCase
, и вызов connection.close
приводит к сбою этих тестов, поскольку класс TestCase
django оборачивает тест в транзакцию, а закрытие соединения в этой транзакции приводит к разрыву транзакции и вызывает django.db.transaction.TransactionManagementError
.
Одна из попыток решить эту проблему, которую я пробовал, заключается в установке параметра базы данных CONN_MAX_AGE
и вызове вместо этого connection.close_if_unusable_or_obsolete
, но транзакция также изменяет параметр autocommit
соединения со значения по умолчанию True
на False
, что, в свою очередь, заставляет close_if_unusable_or_obsolete
попытаться закрыть соединение в любом случае. (https://github.com/django/django/blob/master/django/db/backends/base/base.py#L497).
Я думаю, я мог бы также издеваться над connection.close
в тесте, чтобы он ничего не делал, но это выглядит как хакерство.
Каков наилучший способ протестировать метод django, который должен закрыть соединение с базой данных?