2015-03-30 20 views
6

Czy można wywołać wywołanie zwrotne chord, nawet jeśli główne zadania nie powiodły się?Wywołanie zwrotnego akordu, nawet jeśli główne zadania zakończą się niepowodzeniem

Stworzyłem akord, do którego dodałem kilka zadań i zarejestrowałem wywołanie zwrotne. Mój problem polega na tym, że jeśli jedno z zadań nie powiedzie się, wywołanie zwrotne nie zostanie wywołane, ale chciałbym, aby wywołanie zwrotne zostało uruchomione w obu kierunkach.

Próbowałem zarejestrować zwrotnego Si() (immutability)

callback = tasks.run_delete_rule.si([timestamp]) 
header = [tasks.run_update_rule.s(i, timestamp) for i in item_ids] 
result = chord(header)(callback) 

Próbowałem też dodać param ignore_result=True zarówno zadania dekoratora, ale bez powodzenia.

+1

Szukam tego samego rozwiązania. –

Odpowiedz

5

Z github emisji #1881 jeżeli zwrotna ma zestaw link_error opcja, która pobiera listę nazw zadań, a następnie, gdy zadanie cięciwy nie zadania link_error będą wykonywane.

@task(name='super_task.good') 
def good(): 
    return True 

@task(name='super_task.raise_exception') 
def raise_exception(): 
    raise ValueError('error') 

@task(name='super_task.callback') 
def callback(*args, **kwargs): 
    logger.info('callback') 
    logger.info(args) 
    logger.info(kwargs) 
    return 'finished' 

@task(name='super_task.error_callback') 
def error_callback(*args, **kwargs): 
    logger.info('error_callback') 
    logger.info(args) 
    logger.info(kwargs) 
    return 'error' 

>>> c = chord(
     [raise_exception.s(), good.s(), raise_exception.s()], 
     callback.s().set(link_error=['super_task.error_callback']) 
    ) 
>>> result = c() 

ten wykona akord iw dzienniku selera, zobaczysz zadanie raise_exception niepowodzeniem i wykonanie error_callback który otrzyma w to args z task_id z callback.

W tym momencie wartość result zawierać będzie wystąpienie callbackAsyncResult, a ze względu na akord błędy propagowane do zwrotnego robi result.get() podniesie wyjątek zadań i result.traceback daje traceback.

Jeśli chcesz mieć jeden zwrotnego, po prostu przekazać nazwę zwrotnego akordów do link_error

callback.s().set(link_error='super_task.callback') 

UWAGA

Another opcje To ustawienie CELERY_CHORD_PROPAGATES = False który powróci do wcześniej selera 3.1 zachowanie i zawsze wywoływać wywołanie zwrotne.

Ale nie jest to zalecane podejście, bo jak można znaleźć w numerze github #1349

Seler 3,1 określa, jak błędy akordów są obsługiwane, poprzednie zachowanie nigdy nie zostało udokumentowane i więcej od wypadku, ponieważ nigdy nie było intencją pracy w ten sposób.

Nie mogliśmy zmienić zachowania w wydaniu poprawkowym, dlatego trzeba było użyć ustawienia, , ale nigdy nie było intencją, aby ktoś świadomie wyłączył nowe zachowanie.

Nowe zachowanie ma na celu ochronę przed tego typu problemami, a ustawienie zgodne z poprzednimi wersjami może zostać usunięte. Proponuję znaleźć inny sposób na obsługę błędów tutaj (i nie miałbym nic przeciwko propozycji, jeśli możesz wymyślić dla niej fajne API).

+0

Jak uzyskać wynik dobrego zadania w error_callback? – Carl

+0

@Carl Nie jestem w 100% pewny, ale nie sądzę, że możesz. Sądzę, że jedynymi atrybutami, jakie można uzyskać, są wyjątki i ślad po niepowodzeniu zadania.Możesz też użyć magazynu danych, jeśli potrzebujesz czegoś konkretnego, aby można go było odzyskać później, nawet jeśli wszystko zawiedzie. Potrzebowaliśmy go tylko do wysłania i wysłania e-maila, więc nie grałem za bardzo z tym. – alejandrodnm

+0

Zgodnie z kodem akceptacji, otrzymuję komunikat o błędzie, ale funkcja akordów nadal budzi wyjątek, a nie zwraca wartości z wywołania błędu ... – Wesley