Tính Năng Nhiệm Vụ Độc Đáo trong Asynq đảm bảo chỉ có một nhiệm vụ trong hàng đợi Redis.

Khi bạn muốn loại bỏ các nhiệm vụ trùng lặp và tránh các nhiệm vụ bị trùng, tính năng này rất hữu ích.

Tổng quan

Có hai phương pháp để đảm bảo tính duy nhất của nhiệm vụ trong Asynq.

  1. Sử dụng tùy chọn TaskID: Tự tạo một ID nhiệm vụ duy nhất.
  2. Sử dụng tùy chọn Unique: Cho phép Asynq tạo một khóa duy nhất cho nhiệm vụ.

Sử dụng Tùy chọn TaskID

Nếu bạn chọn phương pháp đầu tiên, bạn có thể đảm bảo chỉ có một nhiệm vụ với ID nhiệm vụ cụ thể vào bất kỳ thời điểm nào. Nếu bạn cố gắng đưa vào hàng đợi một nhiệm vụ khác với cùng ID nhiệm vụ, nó sẽ trả về lỗi ErrTaskIDConflict.

// Nhiệm vụ đầu tiên nên diễn ra bình thường
_, err := client.Enqueue(task, asynq.TaskID("mytaskid"))

// Nhiệm vụ thứ hai sẽ thất bại, biến err sẽ là ErrTaskIDConflict (giả sử nhiệm vụ đầu tiên vẫn chưa được xử lý)
_, err = client.Enqueue(task, asynq.TaskID("mytaskid"))

Sử dụng Tùy chọn Unique

Phương pháp thứ hai dựa trên khóa duy nhất. Khi đưa vào hàng đợi một nhiệm vụ bằng cách sử dụng tùy chọn Unique, Client sẽ kiểm tra xem liệu có thể chấp nhận khóa cho nhiệm vụ cụ thể hay không. Nhiệm vụ chỉ được đưa vào hàng đợi nếu có thể chấp nhận khóa. Nếu một nhiệm vụ khác đã giữ khóa, Client sẽ trả về một lỗi (xem mã ví dụ bên dưới về cách kiểm tra lỗi).

Khóa duy nhất được liên kết với TTL (thời gian tồn tại) để tránh giữ khóa vĩnh viễn. Khóa sẽ được giải phóng sau TTL hoặc sau khi nhiệm vụ được xử lý thành công trước khi TTL hết hạn.

Một điều quan trọng cần lưu ý là tính duy nhất của nhiệm vụ trong Asynq là cố gắng đảm bảo tính duy nhất. Nói cách khác, nếu khóa hết hạn trước khi nhiệm vụ được xử lý, một nhiệm vụ trùng lặp có thể được đưa vào hàng đợi.

Tính duy nhất của nhiệm vụ dựa trên các thuộc tính sau:

  • Loại
  • Tải trọng
  • Hàng đợi

Do đó, nếu có các nhiệm vụ cùng loại và tải trọng được đưa vào hàng đợi cùng hàng đợi, một nhiệm vụ khác với các thuộc tính tương tự sẽ không được đưa vào hàng đợi cho đến khi khóa được giải phóng.

c := asynq.NewClient(redis)

t1 := asynq.NewTask("ví dụ", []byte("xin chào"))

// t1 sẽ giữ khóa duy nhất trong một giờ tới.
err := c.Enqueue(t1, asynq.Unique(time.Hour))
switch {
case errors.Is(err, asynq.ErrDuplicateTask):
    // Xử lý nhiệm vụ trùng lặp
case err != nil:
    // Xử lý lỗi khác
}

t2 := asynq.NewTask("ví dụ", []byte("xin chào"))

// t2 không thể được đưa vào hàng đợi vì nó là bản sao của t1.
err = c.Enqueue(t2, asynq.Unique(time.Hour))
switch {
case errors.Is(err, asynq.ErrDuplicateTask):
    // Xử lý nhiệm vụ trùng lặp
case err != nil:
    // Xử lý lỗi khác
}

Trong ví dụ trên, t2 sẽ không được đưa vào hàng đợi vì nó là bản sao của t1. Bạn có thể sử dụng errors.Is để kiểm tra giá trị error trả về và xác định liệu nó có bao gồm lỗi asynq.ErrDuplicateTask không.