我正在努力更好地理解有关Celery中结果和错误的常见策略。
我看到结果有状态/状态,并在需要时存储结果 - 我什么时候才能使用这些数据?是否应该在任务中包含错误处理和数据存储?
以下是一个示例场景,以防有助于更好地理解我的目标:
我有一个地理编码任务,可以对用户地址进行编码。如果任务失败或成功,我想更新数据库中的一个字段,让用户知道。 (错误处理)成功后,我希望将地理编码数据插入数据库(数据存储)
应该采取什么方法?
答案 0 :(得分:1)
让我先说一下我自己仍然对芹菜的感觉。话虽如此,我对如何解决这个问题有一些普遍的倾向,而且由于没有其他人做出回应,我会试一试。
根据你所写的内容,一个相对简单的(虽然我怀疑是非优化的)解决方案是遵循blog comment spam task example from the documentation的广泛轮廓。
<强> app.models.py 强>
class Address(models.Model):
GEOCODE_STATUS_CHOICES = (
('pr', 'pre-check'),
('su', 'success'),
('fl', 'failed'),
)
address = models.TextField()
...
geocode = models.TextField()
geocode_status = models.CharField(max_length=2,
choices=GEOCODE_STATUS_CHOICES,
default='pr')
class AppUser(models.Model):
name = models.CharField(max_length=100)
...
address = models.ForeignKey(Address)
<强> app.tasks.py 强>
from celery import task
from app.models import Address, AppUser
from some_module import geocode_function #assuming this returns a string
@task()
def get_geocode(appuser_pk):
user = AppUser.objects.get(pk=appuser_pk)
address = user.address
try:
result = geocode_function(address.address)
address.geocode = result
address.geocode_status = 'su' #set address object as successful
address.save()
return address.geocode #this is optional -- your task doesn't have to return anything
on the other hand, you could also choose to decouple the geo-
code function from the database update for the object instance.
Also, if you're thinking about chaining tasks together, you
might think about if it's advantageous to pass a parameter as
an input or partial input into the child task.
except Exception as e:
address.geocode_status = 'fl' #address object fails
address.save()
#do something_else()
raise #re-raise the error, in case you want to trigger retries, etc
<强> app.views.py 强>
from app.tasks import *
from app.models import *
from django.shortcuts import get_object_or_404
def geocode_for_address(request, app_user_pk):
app_user = get_object_or_404(AppUser, pk=app_user_pk)
...etc.etc. --- **somewhere calling your tasks with appropriate args/kwargs
我相信这符合您上面列出的最低要求。我故意将视图保持未开发状态,因为我不知道你想要触发它的确切程度。听起来,当他们的地址无法进行地理编码时,您也可能需要某种用户通知(“我想更新数据库中允许用户知道的字段”)。如果不了解更多有关此要求的具体内容,我会听起来像是在您的html模板中最好完成的事情(如果instance.attribute值为X,在模板中显示q)或使用django.signals(设置为当user.address.geocode_status切换到失败时发出信号 - 例如,通过电子邮件通知用户让他们知道等等。)
在上面代码的注释中,我提到了将上面的get_geocode任务的组件部分解耦和链接的可能性。您还可以考虑通过编写自定义错误处理程序任务并使用link_error parameter(例如。,add.apply_async((2,2),link_error = error_handler.s)将异常处理与get_geocode任务分离。 (),其中 error_handler 已被定义为app.tasks.py中的任务。)此外,无论您选择通过主任务(get_geocode)还是通过链接错误处理程序处理错误,我都会认为你想要更具体地了解如何处理不同类型的错误(例如,做一些连接错误与地址数据格式不正确有关的事情。)
我怀疑有更好的方法,我刚刚开始理解你可以通过链接任务,使用组和和等来获得多么有创造力。希望这有助于至少让你思考一些可能性。我会留给其他人推荐最佳实践。