Halaman ini menjelaskan cara mengkonfigurasi retry tugas.
Perilaku Default
Secara default, asynq
akan melakukan retry tugas maksimal 25 kali. Setiap kali tugas di-retry, akan menggunakan strategi penundaan eksponensial untuk menghitung keterlambatan retry. Jika sebuah tugas menghabiskan semua percobaan retry-nya (defaultnya adalah 25 kali), tugas tersebut akan dipindahkan ke status arsip untuk tujuan debugging dan inspeksi, dan tidak akan di-retry secara otomatis (Anda masih dapat menjalankan tugas secara manual menggunakan CLI atau WebUI).
Berikut adalah properti retry tugas yang dapat disesuaikan:
- Maksimum percobaan retry untuk setiap tugas
- Interval waktu menunggu sebelum tugas yang gagal dapat di-retry (mis., keterlambatan)
- Apakah menggunakan hitungan retry dari tugas
- Apakah untuk melewati retry dan mengirim tugas langsung ke arsip
Bagian-bagian berikut dari halaman ini menjelaskan setiap opsi kustom yang disebutkan di atas.
Menyesuaikan Maksimum Percobaan Retry untuk Tugas
Anda dapat menentukan jumlah maksimum percobaan retry untuk sebuah tugas saat men-queueing tugas menggunakan opsi asynq.MaxRetry
.
Contoh:
client.Enqueue(task, asynq.MaxRetry(5))
Ini menunjukkan bahwa task
harus di-retry paling banyak lima kali.
Atau, jika Anda ingin menetapkan maksimum percobaan retry untuk sebuah tugas tertentu, Anda dapat menetapkannya sebagai opsi default untuk tugas tersebut.
task := asynq.NewTask("feed:import", nil, asynq.MaxRetry(5))
client.Enqueue(task) // MaxRetry diatur ke 5
Menyesuaikan Keterlambatan Retry
Anda dapat menentukan bagaimana menghitung keterlambatan retry menggunakan opsi RetryDelayFunc
pada struktur Config
.
Tanda tangan dari RetryDelayFunc
adalah sebagai berikut:
// n adalah jumlah kali tugas telah di-retry
// e adalah error yang dikembalikan oleh penangan tugas
// t adalah tugas terkait
RetryDelayFunc func(n int, e error, t *asynq.Task) time.Duration
Contoh:
srv := asynq.NewServer(redis, asynq.Config{
Concurrency: 20,
RetryDelayFunc: func(n int, e error, t *asynq.Task) time.Duration {
return 2 * time.Second
},
})
Ini menunjukkan bahwa semua tugas yang gagal akan menunggu selama dua detik sebelum diproses kembali.
Perilaku defaultnya adalah penundaan eksponensial, yang ditentukan oleh DefaultRetryDelayFunc
. Contoh berikut menunjukkan bagaimana menyesuaikan keterlambatan retry untuk jenis tugas tertentu:
srv := asynq.NewServer(redis, asynq.Config{
// Untuk tugas "foo", selalu gunakan keterlambatan 2 detik, tugas lain menggunakan perilaku default.
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)
},
})
Error Non-gagal
Kadang-kadang, Anda mungkin ingin mengembalikan error dari penangan dan mengulangi tugas kemudian, tetapi tanpa menggunakan hitungan retry dari tugas. Misalnya, Anda mungkin ingin mengulangi kemudian karena unit kerja tidak memiliki cukup sumber daya untuk menangani tugas.
Selama inisialisasi server, Anda dapat memilih untuk memberikan Config
untuk fungsi predikat IsFailure(error) bool
. Fungsi predikat ini menentukan apakah error dari penangan dianggap sebagai kegagalan. Jika fungsi tersebut mengembalikan nilai false (yakni, error non-gagal), server tidak akan menggunakan hitungan retry dari tugas dan hanya menjadwalkan tugas untuk di-retry kemudian.
Contoh:
var ErrResourceNotAvailable = errors.New("sumber daya tidak tersedia")
func HandleResourceIntensiveTask(ctx context.Context, task *asynq.Task) error {
if !IsResourceAvailable() {
return ErrResourceNotAvailable
}
// ... logika untuk menangani tugas yang intensif sumber daya
}
// ...
srv := asynq.NewServer(redisConnOpt, asynq.Config{
// ... opsi konfigurasi lainnya
IsFailure: func(err error) bool {
return err != ErrResourceNotAvailable // error non-gagal jika tidak ada sumber daya yang tersedia
},
})
Lewati retry
Jika Handler.ProcessTask
mengembalikan error SkipRetry
, tugas akan diarsipkan terlepas dari sisa jumlah retry. Error yang dikembalikan dapat berupa SkipRetry
atau error yang dibungkus dengan error SkipRetry
.
func ExampleHandler(ctx context.Context, task *asynq.Task) error {
// Logika penangan tugas di sini...
// Jika penangan mengetahui bahwa tugas tidak perlu di-retry, kembalikan SkipRetry
return fmt.Errorf(": %w", asynq.SkipRetry)
}