2012-12-15 32 views
2

我想更好地理解有关结果和芹菜错误的常见策略。芹菜 - 错误处理和数据存储

我看到结果具有状态/状态并存储结果(如果需要) - 何时使用此数据?任务中是否应该包含错误处理和数据存储?

下面是一个示例场景,在情况下,它有助于更​​好的理解我的目标:

我有goeocodes用户地址的地理编码任务。如果任务失败或成功,我想更新数据库中允许用户知道的字段。 (错误处理)成功时,我想要将地理编码数据插入数据库(数据存储)

应该采取什么方法?

回答

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)还是通过链接的错误处理程序处理错误,我都会认为您希望获得更多具体关于如何处理不同类型的错误(例如,做一些连接错误不同于地址数据格式不正确的情况)

我怀疑有更好的方法,我刚开始明白你有多独创通过链接任务,使用组和和弦等获得。希望这有助于至少让你思考ab出一些可能性。我会把它留给其他人来推荐最佳实践。