2017-09-25 15 views
0

私はAPIからデータを取り出し、データベース(SQLite)に関してシステムの自動化(削除、名前変更、...)を行うタスクを持っています。 5分ごとに実行するタスクを設定しました。ただし、タスクが完了するまでに5分以上かかることがあるため、2つのタスクが並行して実行されます。 SQLiteデータベースが0分でタスクにロックされているため、これはうまくいかない。同じタスクが別のタスクで実行されないようにするにはどうすればよいですか?

どのように私はどちらか、持つことができ、

  • 前のタスクが既に終了したか
  • 2番目のタスクキューに入れられたアップと0分のタスクが完了した後、直接実行していない限り、タスクが実行されないのだろうか?

グローバルブールを使用して、実行中のタスクがこのように実行されないようにしようとしました。

automate_is_running = False 
@periodic_task(run_every=timedelta(minutes=5)) 
def automate(): 
    if not automate_is_running: 
     automate_is_running = True 

     automate_all() 

     automate_is_running = False 

しかし、それはUnboundLocalError: local variable 'automate_is_running' referenced before assignmentエラーを返します。私は何をすべきか?

+0

はじめに、関数内で 'global'を使う必要があります。しかし、これはあなたが望むように動作しません。なぜなら、各セロリのワーカーは独自のプロセスであり、データはプロセス間で共有されないからです。たとえば、ディスク上のファイルやdb内のエントリなど、何らかの外部ミューテックスを使用する必要があります。 –

+0

または、一度に1つのタスクのみを実行するワーカーを1人だけ持つこともできますし、各タスクの時間制限を設定することもできます。ここの設定を参照してください:http://docs.celeryproject.org/en/latest/userguide/configuration.html –

答えて

0

まず、機能の中でglobalを使用する必要があります。しかし、これはあなたが望むように動作しません。なぜなら、各セロリのワーカーは独自のプロセスであり、データはプロセス間で共有されないからです。

ディスクのファイルやdbやキャッシュのエントリなど、何らかの外部ミューテックスを使用する必要があります。 memcachedを使用する例はin the Celery cookbookです。

+0

例を見てきましたが、わかりません。私は、必要なパラメータなしで 'automate()'という関数を1つしか持てません。しかし、この例では、「自己」というパラメータがあり、その重要性はわかりません。 – notalentgeek

+0

また、私はこのエラー 'TypeError:automate()missing 1に必要な位置引数 'self'を持っています。 – notalentgeek

+0

これは単なる例です。タスクがクラスのメソッドでない場合は、 'self'を使用しないでください。 –

0

周期的にするのではなく、最初に1回スケジューリングし、タスクの最後に必ず次の実行をスケジュールします。また、失敗したタスクが再試行されていることを確認してください。
エラーTypeError: automate() missing 1 required positional argument: 'self'は、Celery taskデコレータがタスクオブジェクトを作成するため、firs引数としてインスタンスを受け入れる必要があるため、selfです。
次のコードは、タスクをできるだけ早く1回実行し、タスクが正常終了した後は常に300秒後に実行します。また、障害発生時にはできるだけ早く再試行します。
すぐにタスクを再起動するには、self.apply_async(countdown=300)self.delay()に置き換えるか、countdown=0を渡します。

@task 
def automate(self): 
    try: 
     automate_all() 
    except Exception as exc: 
     raise self.retry(exc=exc) 
    else: 
     self.apply_async(countdown=300) 

automate.delay() 

Exceptionの代わりに特別な例外クラスを使用してください。私はあなたのコードが何をしているのか、あなたが期待している例外は何か分かりません。

0

セルラービートでスケジューラを設定し、最初のタスクの最後に2番目のタスクを呼び出すことができます。

celery.py(セロリ2.3)

from django.conf import settings 
from celery.schedules import crontab 

settings.CELERYBEAT_SCHEDULE = { 
    'runs-every-5-minutes' : { 
     'task': 'automate', 
     'schedule': crontab(minute='*/5'), 
     'args' :(), 
    }, 
} 

tasks.py:

from celery import task 

@task(name='automate') 
def automate(): 
    automate_all() 
    run_second_task() 

ドキュメント:

セロリ2.3: http://docs.celeryproject.org/en/v2.3.3/userguide/periodic-tasks.html#crontab-schedules

セロリ4.1 http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html#crontab-schedules

関連する問題