2016-06-19 21 views
0

タスク「CreateNotifications」をランダムな時間間隔で実行する必要があります。 ここでは、CELERYの設定で行ったことがあります。セロリを使ったDjangoでのタスクの非周期的な繰り返し

t = random.randint(45, 85) 
## print "time = ", t 

## celery app configuration 
app.conf.CELERYBEAT_SCHEDULE = { 
    # Executes at every 't' interval, where t is random 
    'create-notifications': { 
     'task': 'apps.notifications.tasks.CreateNotifications', 
     'schedule': timedelta(seconds=t), 
    }, 
} 

今の問題は(私は、コマンドのpython manage.pyののrunserverを実行したとき)CELERYため、これらの設定は、一度だけ実行されるということである、したがって、変数「T」、したがってはtimedeltaの「秒」の値が取得ランダム値ですが、一度だけです。

最終的には、上記のプロセスを一定期間X秒で実行します。サーバーを起動するときにランダムにXだけが選択されます。

これとは別に、私は単一のタスクを実行しようとしましたが、無作為の遅延を伴う無限のwhileループを使用していました。セロリが1つのタスクしか自動検出しないため、そのタスクは終了しません。私の目的は、whileループのランダムな遅延によって解決されます。このよう (NOTE - >関数CreateNotifications()内は「ながら」)

@app.task 
def CreateNotifications(): 

while True: 

    upper_limit = models.MyUser.objects.all().aggregate(Max('id')) 
    lower_limit = models.MyUser.objects.all().aggregate(Min('id')) 

    ## select a user to be notified randomly 

    to_user = None 
    to = 0 

    while to_user is None: 
     to = random.randint(lower_limit['id__min'], upper_limit['id__max']) 
     try: 
      to_user = models.MyUser.objects.get(id=to) 
     except: 
      pass 

    ## select a user to be notified from randomly 

    frm_user = None 
    frm = to 

    while frm_user is None: 
     while frm == to: 
      frm = random.randint(lower_limit['id__min'], upper_limit['id__max']) 
     try: 
      frm_user = models.MyUser.objects.get(id=frm) 
     except: 
      pass 

    notif_type = ['comment on', 'liked', 'shared'] 
    notif_media = ['post', 'picture', 'video'] 

    models.Notification.objects.create(
     notified_user = to_user, 
     notifier = frm_user, 
     notification_type = random.choice(notif_type), 
     notification_media = random.choice(notif_media)) 

    to_user.new_notification_count += 1 
    to_user.save() 


    t = random.randint(35, 55) 
    print "delay = ", t 
    time.sleep(t) 

その私が望むとおりに正確なことをやってますが、今は同じタスクを実行する4人の労働者がありますが、私は一つだけにしたいです。

ここに示されているように私は私のvirtualenvの/ bin /ディレクトリにあるcelerydファイルへの変更を試してみた - >Celery. Decrease number of processes

の/ etc /デフォルト/まだありません成功

にはcelerydファイルが存在しないようどんな助けもありがとう。

答えて

1

あなたは本当にセロリのタスクに無限ループを置くべきではありません。専用のプロセスが必要な場合は、セロリではなく独自のプロセスで実行する方がよいでしょう。

タスクが実行されるたびに、今後新しいタスクを再スケジュールすることができます。以下のような何か:

@app.task 
def create_notifications(): 
    try: 
      # 
    finally: 
      t = random.randint(45, 85) 
      create_notifications.apply_async(countdown=t) 

別のオプションは、定期的に実行されますが、近い将来におけるランダムな時間の通知タスクをキュースケジューラタスクを持っているだろう。たとえば、スケジューラタスクが45秒ごとに実行される場合などです。

@app.task 
def schedule_notifications(): 
    t = random.randint(0, 40) 
    create_notifications.apply_async(countdown=t) 
+0

ありがとう@joshua。私の職場の私のメンターが私に同じ修正を教えてくれました。とにかく答えに感謝します。それは正しい方法です。そして、はい、無限ループは避けるべきです。無限ループを使用している間、CELERY PURGE ..を使用してタスクが実行されるのを止めるために、毎回セロリのキューをクリアする必要がありました。私がCreateNotifications.apply_async()をシェルから4回呼び出し、キューからそれらをクリアしていないという事実のために、4人の作業者が作業していました。 –

関連する問題