2011-08-24 18 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に依存しているということです飛行中。そのうちの1つが次のタスクを実行する前に失敗すると、そのタスクは決して再び実行されません。ブローカがディスクに永続化されておらず、そのブローカが(実行中のすべてのタスクを使って)死んだ場合、それらのタスクはどれも実行されません。

これらの問題は、何らかの種類のトランザクションログと定期的な "nanny"タスクによって解決できます。このタスクでは、間に合わない死を迎えて復活させるような繰り返しタスクを見つけることです。

あなたが説明したことを実装しなければならない場合は、これが私のアプローチに近いと思います。

+3

はい、スケジューラは動的スケジュール用に最適化されていませんが、上記のように 'schedule'を' is_due'メソッドで実装することもできます。また、タスク再スケジュール自体は多くの用途に使用できます最初のタスクが常に起動されるようにします。これは簡単ではありません。もう一つの選択肢は、django-celeryでDatabaseSchedulerを使用することです。これは動的スケジュールをサポートし、Djangoプロジェクトの外でも使用できます。さらに、独自のスケジューラを作成することはそれほど難しいことではありません。 – asksol

+0

@asksol、django-celeryのドキュメントは空です。databaseSchedulerの使い方はどこで知ることができますか? – goh

+1

@amateur文書は実際にはほんのわずかです。 – asksol

1

celery.task.base.PeriodicTaskは、次の実行がいつ行われるかを決定するis_dueを定義します。この関数をオーバーライドして、カスタム動的実行ロジックを含めることができます。カスタムスケジュールを定義したらhttp://celery.readthedocs.org/en/latest/faq.html#can-i-change-the-interval-of-a-periodic-task-at-runtime

...これはあなたにいくつかのを助けるべき

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

私は実行時にオーバーライドする方法の例を教えていただけますか? periodicTaskクラスのrun()がないので、私は.delayを使用できないと思います。 – goh

+0

独自のスケジュールクラス(celery.schedules.schedule)をカスタムis_dueメソッドで定義します。 'CELERYBEAT_SCHEDULE = {" my name ":{"タスク ":" myapp.mytask "、スケジュール":myschedule()}} ' – asksol

0

、asksolが持っているとして、あなたのタスクに割り当て:http://docs.celeryproject.org/en/latest/reference/celery.task.base.html?highlight=is_due#celery.task.base.PeriodicTask.is_due

例:ここではドキュメントを参照してください。上記で提案された。

CELERYBEAT_SCHEDULE = {  
    "my_name": { 
     "task": "myapp.tasks.task", 
     "schedule": myschedule(),  
    } 
} 

また、あなたはあなたのスケジュールをより頻繁に5分ごとよりも更新したい場合はCELERYBEAT_MAX_LOOP_INTERVALを変更したい場合があります。

関連する問題