คุณลักษณะงานที่ไม่ซ้ำกันใน Asynq ทำให้มั่นใจได้ว่ามีเพียงงานเดียวในคิว Redis เท่านั้น

เมื่อคุณต้องการลบงานที่ซ้ำกันและป้องกันไม่ให้มีงานที่ซ้ำกัน คุณลักษณะนี้เป็นประโยชน์อย่างมาก

ภาพรวม

มีวิธีการสองประการในการให้คุณลักษณะงานที่ไม่ซ้ำกันใน Asynq

  1. การใช้ตัวเลือก TaskID : สร้างรหัสงานที่ไม่ซ้ำกันเอง
  2. การใช้ตัวเลือก Unique : ให้ Asynq สร้างการล็อกที่ไม่ซ้ำกันสำหรับงาน

การใช้ TaskID Option

หากคุณเลือกวิธีการแรก คุณสามารถมั่นใจได้ว่ามีเพียงงานเดียวที่มีรหัสงานที่กำหนดไว้ในทุกเวลาที่กำหนด หากคุณพยายามใส่งานอีกครั้งที่มีรหัสงานเดียวกัน มันจะส่งคืนข้อผิดพลาด ErrTaskIDConflict

// งานแรกควรทำได้
_, err := client.Enqueue(task, asynq.TaskID("mytaskid"))

// งานที่สองจะทำล้มเหลว  err จะเป็น ErrTaskIDConflict (โดยสมมติว่างานแรกยังไม่ได้รับการประมวลผล)
_, err = client.Enqueue(task, asynq.TaskID("mytaskid"))

การใช้ Unique Option

วิธีการที่สองเป็นการล็อกที่ไม่ซ้ำกัน เมื่อนำงานเข้าคิวโดยใช้ตัวเลือก Unique ตัว Client จะตรวจสอบว่าสามารถได้รับล็อกสำหรับงานที่กำหนดหรือไม่ งานจะถูกนำเข้าคิวเฉพาะเมื่อสามารถได้รับล็อก หากมีงานอื่นถือครองล็อกอยู่แล้ว, ตัว Client จะส่งคืนข้อผิดพลาด (ดูตัวอย่างโค้ดด้านล่างเพื่อทบทวนว่าวิธีการแก้ปัญหาข้อผิดพลาด)

ล็อกที่ไม่ซ้ำกันเชื่อมโยงกับ TTL (time to live) เพื่อหลีกเลี่ยงการถือล็อกอยู่ตลอดไป ล็อกจะถูกปล่อยหลังจาก TTL หรือหลังจากงานได้รับการประมวลผลเรียบร้อยก่อน TTL

สิ่งที่สำคัญที่จะทำความเข้าใจคือ คุณลักษณะงานที่ไม่ซ้ำกันใน Asynq เน้นการล็อกที่ไม่ซ้ำกันด้วยความพยายาม ที่ดีที่สุด กล่าวคือ หากล็อกได้หมดอายุก่อนที่งานได้รับการประมวลผล งานที่ซ้ำกันอาจนำเข้าคิวได้

คุณลักษณะงานที่ไม่ซ้ำกันขึ้นอยู่กับลักษณะต่อไปนี้:

  • ประเภท
  • ดาวน์โหลด
  • คิว

ดังนั้น, หากมีงานที่มีประเภทและดาวน์โหลดเหมือนกันถูกนำเข้าคิวไปยังคิวเดียวกัน, งานอื่นที่มีลักษณะเหล่านี้เหมือนกันจะไม่ถูกนำเข้าคิวไปยังคิวเดียวกันจนกว่าล็อกจะถูกปล่อย

c := asynq.NewClient(redis)

t1 := asynq.NewTask("example", []byte("hello"))

// t1 จะถือล็อกที่ไม่ซ้ำกันไว้ถึง 1 ชั่วโมงถัดไป
err := c.Enqueue(t1, asynq.Unique(time.Hour))
switch {
case errors.Is(err, asynq.ErrDuplicateTask):
    // จัดการกับงานที่ซ้ำกัน
case err != nil:
    // จัดการกับข้อผิดพลาดอื่น ๆ
}

t2 := asynq.NewTask("example", []byte("hello"))

// t2 ไม่สามารถนำเข้าคิวได้เนื่องจากเป็นงานที่ซ้ำกับ t1
err = c.Enqueue(t2, asynq.Unique(time.Hour))
switch {
case errors.Is(err, asynq.ErrDuplicateTask):
    // จัดการกับงานที่ซ้ำกัน
case err != nil:
    // จัดการกับข้อผิดพลาดอื่น ๆ
}

ในตัวอย่างข้างต้น, t2 จะไม่ถูกนำเข้าคิวเนื่องจากเป็นงานที่ซ้ำกันกับ t1 คุณสามารถใช้ errors.Is ในการตรวจสอบค่า error ที่ส่งคืนเพื่อรายงานว่ามันห่อหุ้มข้อผิดพลาด asynq.ErrDuplicateTask หรือไม่