【问题标题】:The right way to call a celery task from Django code?从 Django 代码调用 celery 任务的正确方法?
【发布时间】:2015-09-04 17:52:25
【问题描述】:

我有一个注册表单,在提交后,我想通过一些外部 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()
  # ...

使用 try/except 子句包装 prepare_and_submit_data 的内容并记录错误是否是正确的解决方案?还是把函数的调用封装在寄存器中?

谢谢。

【问题讨论】:

    标签: python django celery djcelery


    【解决方案1】:

    如果任务是异步执行的,延迟调用是非阻塞的,它只是将任务放入消息队列中,然后立即继续执行你的视图代码,这意味着无论任务成功还是失败,它对视图的代码没有任何影响。该声明的例外是:

    • 如果任务队列由于某种原因失败,例如您的消息队列无法访问,因此无法安排任务,在这种情况下,您将在调用prepare_and_submit_data.delay时遇到异常@

    • CELERY_ALWAYS_EAGER 设置为True,这意味着即使您明确请求异步执行任务,它仍然会同步执行,就像您只是调用一样定期阻塞函数 (prepare_and_submit_data())

    我的赌注是后一种情况,您已经正确编写了代码,但上述设置强制它同步执行。不过要考虑的一件事是,几乎可以肯定,当您的视图返回响应时,您将无法获得异步任务的结果。因此,如果您打算在执行视图期间使用异步验证的结果,那么您就不需要异步运行它,您从一开始就在定期同步执行之后。但是,如果您只需要稍后使用它,一种常见的技术是使用从客户端到单独的 API 端点的定期 ajax 请求,它应该检查您的任务是否完成了它的执行并返回结果。

    【讨论】:

      猜你喜欢
      • 2013-08-30
      • 2018-01-20
      • 2016-09-28
      • 2019-07-02
      • 2020-02-29
      • 1970-01-01
      • 2013-10-14
      • 1970-01-01
      • 2021-09-27
      相关资源
      最近更新 更多