2011-08-17 23 views

Odpowiedz

12

Można budować swoją własną metodę pomocniczą w Groovy do hermetyzacji tę logikę ponawiania.

def retry(int times = 5, Closure errorHandler = {e-> log.warn(e.message,e)} 
    , Closure body) { 
    int retries = 0 
    def exceptions = [] 
    while(retries++ < times) { 
    try { 
     return body.call() 
    } catch(e) { 
     exceptions << e 
     errorHandler.call(e) 
    }   
    } 
    throw new MultipleFailureException("Failed after $times retries", exceptions) 
} 

(Przyjmując definicję MultipleFailureException podobną do GPars' AsyncException)

następnie w kodzie, można użyć tej metody w następujący sposób.

retry { 
    errorProneOperation() 
} 

lub z innej liczby prób i zachowań obsługi błędów:

retry(2, {e-> e.printStackTrace()}) { 
    errorProneOperation() 
} 
+1

Teraz jeśli 'IllegalStateException' użyłby jeden z wyjątków (pierwszy ostatni trudno powiedzieć?), Jak jego przyczyna, byłaby ** dużo ** bardziej przydatna, jak mogłeś zobaczyć ** dlaczego ** to się nie udało. W produkcji nie chciałbym drukować stacktrace za każdym razem, gdy próba nie powiodła się. Chcę tylko o tym wiedzieć, jeśli wszystkie powtórzenia nie powiodły się. –

+0

Dzięki Joachim - za Twoją sugestię dodałem w zbieraniu poszczególnych wyjątków. A jeśli chodzi o brak szukania stosu, to tylko po to, żeby to zilustrować. Ponieważ obecnie zbierane są wyjątki, aby zgłosić je na końcu, być może celem errorHandler jest zresetowanie zasobów, które są wymagane, zanim 'body.call()' zostanie ponowione - w takim przypadku domyślnym zamknięciem może być '{->} ' – winstaan74

+0

Skończyło się na użyciu czegoś bardzo podobnego. dzięki winstaan. –

1

W dzisiejszych czasach ludzie zalecają stosowanie ScheduledExecutorService do implementacji tego rodzaju funkcji "próbuj złapać", ponieważ Thread.sleep() jest uważana za przestarzałą i potencjalnie szkodliwą dla wydajności. Miałem zamiar wskazać ci dobrą odpowiedź na ten temat, ale nie mogę tego dla mnie znaleźć. Zaktualizuję moją odpowiedź, jeśli uda mi się ją wykopać.

EDYCJA: Znalezione: How to retry function request after a certain time Mam nadzieję, że jest to dla ciebie pomocne.

1

mogę zaproponować naśladować trochę takie same (nie jestem pewien o semantyce retry):

def retry(handler, c) { 
    try { 
     c() 
    } catch(e) { 
     handler(e) 
     retry(handler, c) // restart from beginning 
    } 
} 

def handler = {e -> 
    // handles error 
} 

retry(handler) { 
    do_something // exception raised 
}