Запрос на совпадение с Django не существует после сохранения объекта в задаче Celery
У меня есть следующий код:
@task()
def handle_upload(title, temp_file, user_id):
.
.
.
photo.save()
#if i insert here "photo2 = Photo.objects.get(pk=photo.pk)" it works, including the view function
return photo.pk
#view function
def upload_status(request):
task_id = request.POST['task_id']
async_result = AsyncResult(task_id)
photo_id = async_result.get()
if async_result.successful():
photo = Photo.objects.get(pk=photo_id)
Я использую ajax-запрос для проверки загруженного файла, но после того, как задача сельдерея завершается, я получаю, что запрос на сопоставление фотографий не существует. Фото ПК существует и возвращается. Если я запрашиваю базу данных вручную, это работает. Это какая-то задержка базы данных? Как я могу это исправить? Я использую Django 1.4 и Celery 3.0
1 ответ
Вы можете подтвердить, является ли это проблемой с задержкой, добавив задержку в ваше представление django, чтобы подождать, пока задача успешно завершится в течение нескольких секунд. Если это решит проблему, вы можете захотеть обернуть handle_upload в транзакцию, чтобы заблокировать ее, пока БД полностью не подтвердит, что она закончила перед возвратом.
Кроме Django, DB тоже имеет свои кеши. Когда django вызывает набор запросов, он получает устаревшие данные либо из своих собственных кэшей (маловероятно, если вы не использовали повторно наборы запросов, чего я не видел в части кода, которую вы разместили), либо БД не кэширует результаты для того же соединения Django.
Например, если бы вы вызвали постобработку после завершения задачи сельдерея в совершенно новом запросе / просмотре django, вы, вероятно, увидели бы новые изменения в БД просто отлично. Тем не менее, поскольку ваше представление было заблокировано во время выполнения задачи (что отрицательно сказывается на назначении сельдерея, кстати), внутренне django сохраняет снимок БД только во время ввода представления. Поэтому ваш get завершается неудачно, и вы подтвердили это поведение, просто войдя в оболочку django.
Вы можете исправить это, как вы уже сделали:
- вызывая управление транзакциями, которое обновит снимок
- изменение политик кэширования конечной точки вашей БД и политики автоматической фиксации
- пусть сельдерей сделает обратный вызов django (веб-запрос), как только это будет сделано, чтобы завершить обработку (что, скорее всего, то, что вы хотите сделать в любом случае, потому что блокировка django побеждает цель)