После некоторого дальнейшего исследования кажется, что есть проблемы с соединениями с базой данных и возможной безопасностью потоков при объединении асинхронных и сельдерейных программ, которые я не до конца понимаю.
Решение, которое, кажется, работает такдалеко было создать новую функцию:
from django.db import connections
from django.conf import settings
def reset_db_connections():
if not settings.CELERY_TASK_ALWAYS_EAGER:
connections.close_all()
Я называю эту функцию первой строкой любой задачи сельдерея:
@shared_task(bind=True)
def my_celery_task(self, args):
reset_db_connections()
# do stuff
# call stuff that uses asyncio
Пока что, похоже, мой код работаетнезависимо от того, какая у меня настройка для CELERY_TASK_ALWAYS_EAGER
.
Первоначально вместо connections.close_all()
я пытался:
for conn in db.connections.all():
if conn.connection.closed != 0:
conn.connection.close()
, но это приводило к ошибкам, когда я не закрывал соединения, которые нужно было закрыть, и / или я закрывал соединения, которые былиуже закрыт.
В качестве альтернативы вышеприведенному решению я обнаружил, что изменяя настройку:
DATABASES = {"default": dj_database_url.config(conn_max_age=600)}
на
DATABASES = {"default": dj_database_url.config(conn_max_age=0)}
также решил проблему.Однако, насколько я понимаю, установка conn_max_age=0
будет использовать новое соединение для каждой операции с БД, что не кажется хорошей идеей.С подходом reset_db_connections()
, приведенным выше, я могу оставить conn_max_age=600
.