2014-09-10 224 views
2

我試圖找到一種方法,可以從django管理員打開/關閉芹菜任務。這主要是爲了禁用在這些服務關閉或具有計劃的維護期時調用外部服務的任務。關掉芹菜任務

對於我的定期任務,這很容易,尤其是在django-celery中。但對於按需調用的任務,我遇到了一些麻煩。目前,我正在探索在TaskControl模型中存儲各種任務的開/關狀態,然後只在任務執行開始時檢查該狀態,如果狀態爲False則返回None。這讓我感覺很髒,因爲每次任務開始時都會有額外的db查詢。我可以使用不是數據庫的緩存後端,但爲這些少數鍵/值對添加緩存似乎有點矯枉過正。

在models.py

# this is a singleton model. singleton code bits omitted for brevity. 
class TaskControl(models.Model): 
    some_status = models.BooleanField(default=True) 
    # more statuses 

在tasks.py

@celery.task(ignore_result=True) 
def some_task(): 
    task_control = TaskControl.objects.get(pk=1) 
    if not task_control.some_status: 
     return None 

    # otherwise execute task as normal 

什麼是更好的方式來做到這一點?

回答

2

選項1.試試你的簡單方法。看看它是否會影響性能。如果沒有,就會失去「髒」的感覺。

選項2.使用單例緩存進程內存。加入新鮮的信息到你的TaskControl型號:

class TaskControl(models.Model): 
    some_status = models.BooleanField(default=True) 
    # more statuses 
    expires = models.DateTimeField() 
    check_interval = models.IntegerField(default=5 * 60) 

    def is_stale(self): 
     return (
      (datetime.utcnow() >= self.expires) or 
      ((datetime.utcnow() - self.retrieved).total_seconds >= self.check_interval)) 

然後在task_ctl.py

_control = None 

def is_enabled(): 
    global _control 
    if (_control is None) or _control.is_stale(): 
     _control = TaskControl.objects.get(pk=1) 
     # There's probably a better way to set `retrieved`, 
     # maybe with a signal or a `Model` override, 
     # but this should work. 
     _control.retrieved = datetime.utcnow() 
    return _control.some_status 

選項3.像選項2,但不是基於時間的到期,用芹菜的remote control強迫所有工人重新加載TaskControl(你將不得不編寫你自己的控制命令,而且我不知道你需要的所有內部部件是否都是公共API)。

選項4,僅適用於所有芹菜工人都在一臺機器上運行。將開/關標誌作爲文件存儲在該機器的文件系統上。用os.path.exists查詢它的存在(應該是一個單獨的stat()或其他東西,足夠便宜)。如果工作人員和管理面板位於不同的計算機上,請使用特殊的Celery任務創建/刪除文件。

選項5.與選項4一樣,但在管理員/ Web計算機上:如果文件存在,則不要將任務排在首位。

+0

與數字1在一起。性能命中最小,實現也很簡單。感謝您的建議! – ecline6 2014-09-13 23:58:42