условие гонки python django с сельдереем

Работая над проектом python django, вот что я хочу:

  1. Доступ пользователя Page1 с аргументом объекта, функция longFunction() объекта запускается и передается celery, поэтому страница может быть немедленно возвращена

  2. Если пользователь пытается получить доступ к Page2 с тем же аргументом объекта, я хочу, чтобы страница зависала до тех пор, пока функция объекта longFunction(), запущенная Page1, не будет завершена.

Поэтому я попытался заблокировать строку базы данных mysql с помощью objects.select_for_update(), но это не сработало.

Вот упрощенная версия моего кода:

def Page1(request, arg_id):
    obj = Vm.objects.select_for_update().get(id=arg_id)
    obj.longFunction.delay()
    return render_to_response(...)

def Page2(request, arg_id):
    vm = Vm.objects.select_for_update().get(id=arg_id)
    return render_to_response(...)

Я хочу, чтобы Page2 висело на строке vm = Vm.objects.select_for_update().get(id=arg_id), пока не завершится longFunction(). Я новичок в сельдерее, и похоже, что соединение mysql, инициированное на странице 1, теряется, когда страница 1 возвращается, даже если longFunction() не завершена.

Есть ли другой способ добиться этого?

Спасибо


person user2302807    schedule 20.11.2013    source источник


Ответы (2)


Возможно, это может быть полезно для вас:

from celery.result import AsyncResult
from yourapp.celery import app

def Page1(request, arg_id):
    obj = Vm.objects.select_for_update().get(id=arg_id)
    celery_task_id = obj.longFunction.delay()
    return render_to_response(...)

def Page2(request, arg_id, celery_task_id):
    task = AsyncResult(app=app, id=celery_task_id)
    state = task.state
    while state != "SUCCESFUL":
        # wait or do whatever you want
    vm = Vm.objects.select_for_update().get(id=arg_id)
    return render_to_response(...)

Дополнительная информация на http://docs.celeryproject.org/en/latest/reference/celery.states.html

person Mikel Emaldi Manrique    schedule 20.11.2013
comment
Обратите внимание, что лучше подождать во внешнем интерфейсе, вы можете взглянуть на jobtastic, например: policystat.github.io /jobtastic, что делает это проще. - person asksol; 21.11.2013

Блокировка базы данных от select_for_update снимается при закрытии транзакции (на странице 1). Эта блокировка не переносится на задачу сельдерея. Вы можете заблокировать задачу сельдерея, но это не решит вашу проблему, потому что страница 2 может быть загружена до того, как задача сельдерея получит блокировку.

Ответ Микеля будет работать. Вы также можете заблокировать кеш, как описано в поваренной книге сельдерея.

person joshua    schedule 20.11.2013