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)
}