2012-01-17 6 views
8

Ho un processo di lunga durata che deve essere eseguito ogni cinque minuti, ma più di un'istanza dei processi non deve mai essere eseguita contemporaneamente. Il processo normalmente non dovrebbe superare i cinque minuti, ma voglio essere sicuro che una seconda istanza non si avvii se viene eseguita.Django Celery: esegue solo un'istanza di un processo di lunga durata

Per un previous recommendation, sto usando Django Celery per pianificare questa attività di lunga durata.

Non penso che un'attività periodica funzioni, perché se ho un periodo di cinque minuti, non voglio eseguire una seconda attività se un'altra istanza dell'attività è già in esecuzione.

Il mio esperimento corrente è il seguente: alle 8:55, un'istanza dell'attività inizia a essere eseguita. Quando l'attività si sta concludendo, attiverà un'altra istanza di se stessa per essere eseguita al successivo contrassegno di cinque minuti. Quindi, se la prima attività termina alle 8:57, la seconda attività verrà eseguita alle 9:00. Se il primo compito si verifica eseguendosi a lungo e finendo alle 9:01, pianifica l'esecuzione dell'istanza successiva alle 9:05.

Ho sofferto con una varietà di errori criptici quando ho fatto qualcosa di più del semplice esempio di seguito e non ho trovato nessun altro esempio di persone che pianificano compiti da una precedente istanza di se stesso. Mi chiedo se ci sia forse un approccio migliore per fare ciò che sto cercando di fare. So che c'è un modo per nominare i propri compiti; forse c'è un modo per cercare istanze in esecuzione o pianificate con lo stesso nome? Qualcuno ha qualche consiglio da offrire per quanto riguarda l'esecuzione di un'attività ogni cinque minuti, ma assicurandosi che venga eseguito un solo compito alla volta?

Grazie, Joe

In mymodule/tasks.py:

import datetime 
from celery.decorators import task 

@task 
def test(run_periodically, frequency): 

    run_long_process() 
    now = datetime.datetime.now() 
    # Run this task every x minutes, where x is an integer specified by frequency 
    eta = (
     now - datetime.timedelta(
     minutes = now.minute % frequency , seconds = now.second, 
     microseconds = now.microsecond)) + datetime.timedelta(minutes=frequency) 
    task = test.apply_async(args=[run_periodically, frequency,], eta=eta) 

Da un guscio ./manage.py:

from mymodule import tasks 
result = tasks.test.apply_async(args=[True, 5]) 

risposta

7

È possibile utilizzare attività periodiche abbinate a un blocco speciale che garantisce che le attività vengano eseguite una alla volta. Ecco un esempio di implementazione da documentazione Sedano:

http://ask.github.com/celery/cookbook/tasks.html#ensuring-a-task-is-only-executed-one-at-a-time

tuo metodo descritto con compiti di pianificazione dall'esecuzione precedente può fermare l'esecuzione dei compiti se ci sarà il fallimento in uno di essi.

+0

Grazie 0x00mh. Questo è un link pulito. Ci sto provando. –