2011-08-24 87 views

回答

7

時間表是derived from a setting,因此在運行時似乎是不可變的。

您可以使用Task ETAs或許可以完成要查找的內容。這保證你的任務不會在之前運行所需的時間,但不會承諾在指​​定的時間運行任務 - 如果工作人員在指定的ETA超載,任務可能會在稍後運行。

如果限制是不是一個問題,你可以寫這將首先運行本身就像一個任務:

@task 
def mytask(): 
    keep_running = # Boolean, should the task keep running? 
    if keep_running: 
     run_again = # calculate when to run again 
     mytask.apply_async(eta=run_again) 
    # ... do the stuff you came here to do ... 

這種方法的主要缺點是,你是依靠taskstore記住任務在飛行中。如果其中一個在發射下一個失敗之前失敗,那麼該任務將永不再運行。如果您的經紀人沒有堅持到磁盤並且死亡(將所有的飛行任務與它一起),那麼這些任務都不會再次運行。

你可以通過某種事務日誌記錄和週期性的「保姆」任務來解決這些問題,該任務的任務是找到這樣的重複任務,以避免死亡並使其復活。

如果我必須實現你所描述的內容,我認爲這是我將如何處理它。

+3

是的,調度程序沒有針對動態調度進行優化,但是您可以使用上面描述的'is_due'方法實現您自己的'Schedule',同時讓任務重新調度本身也是許多使用的選項,但是您需要確保始終觸發第一項任務,這並不容易。另一種選擇是在django-celery中使用DatabaseScheduler,它支持動態調度,也可以在Django項目之外使用。另外,創建自己的調度程序並不困難。 – asksol

+0

@asksol,django-芹菜的文件是空的。我在哪裏可以找到如何使用databaseScheduler? – goh

+1

@amateur呃,這裏的文檔真的很稀少: – asksol

1

celery.task.base.PeriodicTask定義is_due它決定了下一次運行的時間。您可以重寫此函數以包含您的自定義動態運行邏輯。在這裏看到的文檔:http://docs.celeryproject.org/en/latest/reference/celery.task.base.html?highlight=is_due#celery.task.base.PeriodicTask.is_due

一個例子:

import random 
from celery.task import PeriodicTask 

class MyTask(PeriodicTask): 

    def run(self, **kwargs): 
     logger = self.get_logger(**kwargs) 
     logger.info("Running my task") 

    def is_due(self, last_run_at): 
     # Add your logic for when to run. Mine is random 
     if random.random() < 0.5: 
      # Run now and ask again in a minute 
      return (True, 60) 
     else: 
      # Don't run now but run in 10 secs 
      return (True, 10) 
+0

可以給我一個如何在運行時重寫的例子嗎?我認爲我不能使用.delay,因爲沒有爲週期性任務運行()的類 – goh

+0

您可以使用自定義的is_due方法定義自己的調度類(celery.schedules.schedule)。 'CELERYBEAT_SCHEDULE = {「my name」:{「task」:「myapp.mytask」,schedule「:myschedule()}} – asksol

相關問題