2012-12-15 44 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出一些可能性。我會把它留給其他人來推薦最佳實踐。