Правильный способ вызвать задачу сельдерея из кода Джанго?

У меня есть форма регистрации, которая после отправки я хочу выполнить некоторую проверку данных через некоторые внешние API, а затем в конечном итоге передать другой API. Я хочу сделать это асинхронно, чтобы отправитель не ждал 10 секунд для отправки формы.

Пока это мой код - он работает, но если в задаче возникает исключение, пользователь получает ошибку 500 (конкретное исключение состоит в том, что иногда сторонний API я использую время ожидания). У меня сложилось впечатление, что если задача выполняется асинхронно (обратите внимание на декоратор @task и используя задержку для вызова задачи), тогда загрузка страницы успеха должна происходить независимо от того, что происходит в функции.

views.py

from myapp.tasks import prepare_and_submit_data

def register(request):
  form = SignupForm(request.POST or None)
  if form.is_valid():

    # Async function.
    prepare_and_submit_data.delay(form.cleaned_data)

    return render(request, 'success.html', {})
  return render(request, 'signup.html', {'form': form})

tasks.py

from celery.decorators import task

@task
def prepare_and_submit_data(data):
  # do some external API requests and modify data
  data = requests.post(BASE_URL, data=data).json()
  # ...

Это правильное решение, чтобы обернуть содержимое prepare_and_submit_data с предложением try/exc и записать ошибку? Или обернуть вызов функции в регистр?

Спасибо.

1 ответ

Если задача выполняется асинхронно, вызов задержки не является блокирующим, она просто помещает задачу в очередь сообщений и сразу же продолжает выполнение кода вашего представления, что означает, что независимо от того, успешно ли выполняется задача или нет, она может: не имеет никакого влияния на код представления. Исключением из этого утверждения являются:

  • если по какой-либо причине возникла ошибка в очереди задач, например, ваша очередь сообщений недоступна, поэтому задача не может быть запланирована, в этом случае вы получите исключение при вызове prepare_and_submit_data.delay

  • CELERY_ALWAYS_EAGER установлен в TrueЭто означает, что даже когда вы явно запрашиваете, чтобы задача выполнялась асинхронно, она, тем не менее, будет выполняться синхронно, как если бы вы просто регулярно вызывали блокирующую функцию (prepare_and_submit_data())

Я держу пари на последнем случае, вы правильно написали код, но вышеупомянутая настройка заставляет его выполняться синхронно. Однако следует учитывать одну вещь: почти наверняка у вас не будет результатов асинхронной задачи, когда ваше представление вернет ответ. Таким образом, если вы намеревались использовать результат асинхронной проверки во время выполнения вашего представления, то вам просто не нужно запускать его асинхронно, вы были после обычного синхронного выполнения с самого начала. Но, если вам нужно использовать его только позже, распространенным методом является использование периодических запросов AJAX со стороны клиента к отдельной конечной точке API, которая должна проверить, завершила ли ваша задача выполнение и вернуть результаты.

Другие вопросы по тегам