Ta strona opisuje, jak skonfigurować ponowne próby zadania.
Domyślne zachowanie
Domyślnie, asynq
spróbuje ponownie wykonać zadanie maksymalnie 25 razy. Za każdym razem, gdy zadanie jest ponawiane, obliczany jest opóźnienie za pomocą strategii wykładniczego powrotu. Jeśli zadanie wyczerpie wszystkie próby ponownego wykonania (domyślnie 25 razy), zadanie zostanie przeniesione do stanu zarchiwizowanego w celach debugowania i inspekcji, i nie będzie ponownie wykonywane automatycznie (nadal można ręcznie uruchomić zadanie za pomocą interfejsu wiersza poleceń (CLI) lub interfejsu użytkownika sieciowego (WebUI)).
Następujące właściwości ponownych prób zadania można dostosować:
- Maksymalna liczba prób ponownego wykonania dla każdego zadania
- Interwał czasowy oczekiwania przed ponowną próbą wykonania nieudanego zadania (tj. opóźnienie)
- Czy używać liczby ponownych prób zadania
- Czy pominąć ponowne próby i wysłać zadanie bezpośrednio do archiwum
Pozostałe części tej strony opisują każdą z powyższych opcji niestandardowych.
Dostosowywanie Maksymalnej Liczby Prób Ponownego Wykonania Zadań
Możesz określić maksymalną liczbę prób ponownego wykonania zadania podczas jego enqueuingu, korzystając z opcji asynq.MaxRetry
.
Przykład:
client.Enqueue(task, asynq.MaxRetry(5))
Znaczy to, że task
powinno być ponawiane maksymalnie pięć razy.
Alternatywnie, jeśli chcesz ustawić maksymalną liczbę prób ponownego wykonania dla konkretnego zadania, możesz ustawić ją jako domyślną opcję dla zadania.
task := asynq.NewTask("feed:import", nil, asynq.MaxRetry(5))
client.Enqueue(task) // MaxRetry ustawione na 5
Dostosowywanie Opóźnienia Ponownej Próby
Możesz określić sposób obliczania opóźnienia ponownej próby za pomocą opcji RetryDelayFunc
w strukturze Config
.
Sygnatura RetryDelayFunc
jest następująca:
// n to liczba razy, kiedy zadanie zostało ponownie uruchomione
// e to błąd zwrócony przez obsługę zadania
// t to powiązane zadanie
RetryDelayFunc func(n int, e error, t *asynq.Task) time.Duration
Przykład:
srv := asynq.NewServer(redis, asynq.Config{
Concurrency: 20,
RetryDelayFunc: func(n int, e error, t *asynq.Task) time.Duration {
return 2 * time.Second
},
})
Znaczy to, że wszystkie nieudane zadania będą czekać dwa sekundy przed ponownym przetwarzaniem.
Domyślne zachowanie to wykładniczy powrót, zdefiniowany przez DefaultRetryDelayFunc
. Poniższy przykład demonstruje, jak dostosować opóźnienie ponownej próby dla określonych typów zadań:
srv := asynq.NewServer(redis, asynq.Config{
// Dla zadań "foo" zawsze użyj 2-sekundowego opóźnienia, inne zadania używają domyślnego zachowania.
RetryDelayFunc: func(n int, e error, t *asynq.Task) time.Duration {
if t.Type() == "foo" {
return 2 * time.Second
}
return asynq.DefaultRetryDelayFunc(n, e, t)
},
})
Błąd niezwiązany z niepowodzeniem
Czasami możesz chcieć zwrócić błąd z obsługi i ponownie spróbować zadanie później, ale bez użycia liczby prób ponownego wykonania zadania. Na przykład, możesz chcieć spróbować ponownie później, ponieważ jednostka robocza nie ma wystarczających zasobów do obsługi zadania.
Podczas inicjalizacji serwera, możesz wybrać dostarczenie Config
dla funkcji predykatu IsFailure(error) bool
. Ta funkcja predykatu określa, czy błąd z obsługi jest uznawany za niepowodzenie. Jeśli funkcja zwraca wartość fałsz (tj. błąd niezwiązany z niepowodzeniem), serwer nie będzie korzystać z liczby prób ponownego wykonania zadania i po prostu zaplanuje zadanie do późniejszej ponownej próby.
Przykład:
var ErrResourceNotAvailable = errors.New("no resource is available")
func HandleResourceIntensiveTask(ctx context.Context, task *asynq.Task) error {
if !IsResourceAvailable() {
return ErrResourceNotAvailable
}
// ... logika obsługi zadania wymagającego zasobów
}
// ...
srv := asynq.NewServer(redisConnOpt, asynq.Config{
// ... inne opcje konfiguracyjne
IsFailure: func(err error) bool {
return err != ErrResourceNotAvailable // błąd niezwiązany z niepowodzeniem, jeśli nie ma dostępnych zasobów
},
})
Pominięcie ponownego wykonywania
Jeśli Handler.ProcessTask
zwraca błąd SkipRetry
, zadanie zostanie zarchiwizowane niezależnie od pozostałej liczby ponownych prób. Zwracany błąd może być SkipRetry
lub błąd opakowany w błąd SkipRetry
.
func ExampleHandler(ctx context.Context, task *asynq.Task) error {
// Logika obsługi zadania tutaj...
// Jeśli obsługa wie, że zadanie nie powinno być ponownie wykonywane, zwróć SkipRetry
return fmt.Errorf(": %w", asynq.SkipRetry)
}