2013-07-08 20 views
8

Mi piacerebbe utilizzare django_rq e rq-scheduler per le attività offline, ma non sono sicuro di dove chiamare la capacità di rq-scheduler di pianificare attività ripetitive. In questo momento, ho aggiunto la mia pianificazione a un modulo tasks.py nella mia app e l'ho importato in __init__ .py. Deve esserci un modo migliore per farlo, però, giusto?Dove posso registrare un lavoro rq-scheduler in un'app Django?

Grazie in anticipo.

+0

Penso - da nessuna parte. Ogni volta che si riavvia il server delle applicazioni, i lavori verranno aggiunti alla coda del programma di pianificazione (le attività verranno moltiplicate per ogni avvio). Per risolvere il problema, è possibile cancellare/rimuovere la chiave 'rq: scheduler: scheduled_jobs' su ogni avvio, prima di aggiungerli. Ma ricorda di evitare di aggiungere/rimuovere lavori nei processi di lavoro - Non ho idea di come ottenerlo. – marcinn

risposta

9

Ho aggiunto la pianificazione a un modulo __init__ in una delle mie applicazioni di progetto (in termini di Django), ma avvolto con una piccola funzione che impedisce l'accodamento di due o più processi. La strategia di pianificazione può dipendere dalle vostre esigenze specifiche (ad esempio, potrebbe essere necessario un controllo aggiuntivo per gli argomenti di un lavoro).

codice che funziona per me e adatta alle mie esigenze:

import django_rq 
from collections import defaultdict 
import tasks 

scheduler = django_rq.get_scheduler('default') 

jobs = scheduler.get_jobs() 
functions = defaultdict(lambda: list()) 

map(lambda x: functions[x.func].append(x.meta.get('interval')), jobs) 

now = datetime.datetime.now() 

def schedule_once(func, interval): 
    """ 
    Schedule job once or reschedule when interval changes 
    """ 
    if not func in functions or not interval in functions[func]\ 
      or len(functions[func])>1: 

     # clear all scheduled jobs for this function 
     map(scheduler.cancel, filter(lambda x: x.func==func, jobs)) 

     # schedule with new interval 
     scheduler.schedule(now+datetime.timedelta(seconds=interval), func, 
       interval=interval) 

schedule_once(tasks.some_task_a, interval=60*5) 
schedule_once(tasks.some_task_b, interval=120) 

Inoltre ho avvolto questo frammento di evitare importazioni a livello di pacchetto:

def init_scheduler(): 
    # paste here initialization code 

init_scheduler() 
+3

Mi sono appena imbattuto in un inferno che è "scheduling in settings.py". Apparentemente, ogni volta che viene importato, aggiunge di nuovo i lavori pianificati. Avevo lavori che dovevano sparare una volta all'ora accumulandoli nella coda 50 alla volta ....;) –

8

Il posto migliore che ho trovato per eseguirlo è dal tuo AppConfig in apps.py.

def ready(self): 
    scheduler = django_rq.get_scheduler('default') 

    # Delete any existing jobs in the scheduler when the app starts up 
    for job in scheduler.get_jobs(): 
     job.delete() 

    # Have 'mytask' run every 5 minutes 
    scheduler.schedule(datetime.utcnow(), 'mytask', interval=60*5) 
+1

puoi correggere la formattazione? thnx – FeedTheWeb

+1

In che modo django rq rileva questo programmatore? è necessario iniziarlo da qualche parte del codice chiamando la funzione? o se no come posso inizializzarlo automaticamente eseguendo python manage.py rqscheduler? –

+0

Nelle versioni più recenti di Django è possibile creare un file apps.py utilizzato per configurare l'app. Vedi qui per le ultime informazioni: https://docs.djangoproject.com/en/1.9/ref/applications/ –