2016-06-19 4 views
0

Ich muss eine Aufgabe "CreateNotifications" in zufälligen Abständen der Zeit ausführen. Hier ist, was ich in den Einstellungen für CELLERY versucht habe.Nicht-periodische Wiederholung der Aufgabe in Django mit Sellerie

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), 
    }, 
} 

Das Problem ist jetzt, dass diese Einstellungen für SELLERIE nur einmal ausgeführt werden (wenn ich den Befehl python manage.py runserver laufen), also die Variable ‚t‘ und damit der Wert von ‚Sekunden‘ in Timedelta bekommt ein zufälliger Wert, aber nur einmal.

Schließlich wird der obige Prozess zu einem periodischen mit einer festen Periode als X Sekunden, nur X wird zufällig ausgewählt, wenn ich Server starte.

Alternativ habe ich versucht, eine einzelne Aufgabe auszuführen und eine endlose While-Schleife darin mit einer zufälligen Verzögerung verwendet, so dass Sellerie nur eine Aufgabe automatisch erkennt und diese Aufgabe nie endet. Mein Zweck wird durch zufällige Verzögerung in der While-Schleife gelöst. Like this (HINWEIS -> ‚während‘ ist innerhalb der Funktion 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) 

Seine Dinge genau so, wie ich will, aber jetzt gibt es 4 verschiedene Arbeiter die gleiche Aufgabe ausgeführt wird, aber ich möchte nur ein tun .

Ich habe versucht, Änderungen an celeryd Datei in meinem virtualenv/bin/Verzeichnis wie hier angegeben ->Celery. Decrease number of processes

, da es keine celeryd Datei in/etc/defaults ist/aber noch ohne Erfolg

Jede Hilfe wird geschätzt.

Antwort

1

In einer Sellerie-Aufgabe sollte man wirklich keine Endlosschleife machen. Wenn Sie einen dedizierten Prozess benötigen, wäre es besser, ihn auf eigene Faust als durch Sellerie zu betreiben.

Sie könnten eine neue Aufgabe in Zukunft immer dann neu planen, wenn Ihre Aufgabe ausgeführt wird. Etwas wie folgt aus:

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

Eine andere Möglichkeit wäre, einen Scheduler Aufgabe zu haben, die auf einem regelmäßigen Zeitplan läuft aber reiht die Benachrichtigungs Aufgaben für eine zufällige Zeit in der nahen Zukunft. Zum Beispiel, wenn der Scheduler-Task alle 45 Sekunden ausgeführt wird.

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

Dank @joshua. Mein Mentor an meinem Arbeitsplatz sagte mir dasselbe und es funktionierte. Danke trotzdem für die Antwort. Es ist der richtige Weg. Und ja, Endlosschleife sollte vermieden werden. Bei der Verwendung der Endlosschleife musste ich die Sellerie-Warteschlange jedes Mal löschen, um die Ausführung der Aufgaben mithilfe von SELLERY PURGE zu stoppen. Und diese 4 Arbeiter arbeiteten aufgrund der Tatsache, dass ich meine CreateNotifications.apply_async() 4 mal aus der Shell aufgerufen und sie nie aus der Warteschlange gelöscht hatte. –

Verwandte Themen