2012-03-16 26 views
50

dla zadania jak ten:Retry Seler zadania z wykładniczy wycofać

from celery.decorators import task 

@task() 
def add(x, y): 
    if not x or not y: 
     raise Exception("test error") 
    return self.wait_until_server_responds(

jeśli zgłasza wyjątek i chcę ponowić go z boku demona, w jaki sposób można zastosować wykładniczy wycofać algorytmu, czyli po 2^2, 2^3,2^4 itp. Sekund?

Czy powtórzenie jest utrzymywane od strony serwera, tak, że jeśli pracownik zostanie zabity, następny pracownik, który się spawnuje, podejmie zadanie ponownego wykonania?

Odpowiedz

96

Atrybut task.request.retries zawiera liczbę prób dotychczas więc można to wykorzystać do realizacji wykładniczy backoff:

from celery.task import task 

@task(bind=True, max_retries=3) 
def update_status(self, auth, status): 
    try: 
     Twitter(auth).update_status(status) 
    except Twitter.WhaleFail as exc: 
     self.retry(exc=exc, countdown=2 ** self.request.retries) 

Aby zapobiec Thundering Herd Problem, można rozważyć dodanie losowego jitter aby Twój wykładniczy ograniczania:

import random 
self.retry(exc=exc, countdown=int(random.uniform(2, 4) ** self.request.retries)) 
+0

Czy wiesz, czy jest to ponowna próba po stronie serwera, czy też klient musi czekać? Jeśli klient ma czekać, to jest źle. –

+2

O ile mi wiadomo, atrybut odliczający ustawia eta dla zadania na zapleczu MQ (np. RabbitMQ). Więc nie jest ustawiony po stronie klienta. – idanzalz

+0

Klient nie musi czekać, dopóki nie wykonasz 'result.get()', który jest jawnym żądaniem oczekiwania na wynik, aby był gotowy, ale istnieje również argument timeout i istnieje stan RETRY, dzięki czemu możesz sprawdzić, czy zadanie jest ponowna próba (i jaki był powód ponownej próby) – asksol