ميزة المهمة الفريدة في Asynq تضمن وجود مهمة واحدة فقط في طابور الانتظار للريديس.

عندما ترغب في تجنب تكرار المهام وتجنب تكرارها، فإن هذه الميزة مفيدة جدًا.

نظرة عامة

هناك طريقتان لضمان فرادة المهمة في Asynq.

  1. استخدام الخيار TaskID: إنشاء معرف مهمة فريد بنفسك.
  2. استخدام الخيار Unique: السماح لـ Asynq بإنشاء قفل فرادة للمهمة.

استخدام الخيار TaskID

إذا اخترت الطريقة الأولى، يمكنك ضمان وجود مهمة واحدة فقط بمعرف مهمة معين في أي وقت. إذا حاولت إضافة مهمة أخرى بنفس معرف المهمة، سيتم إرجاع خطأ ErrTaskIDConflict.

// يجب أن تكون المهمة الأولى على ما يرام
_, err := client.Enqueue(task, asynq.TaskID("mytaskid"))

// ستفشل المهمة الثانية، وسيكون الخطأ ErrTaskIDConflict (بشرط أن المهمة الأولى لم يتم معالجتها بعد)
_, err = client.Enqueue(task, asynq.TaskID("mytaskid"))

استخدام الخيار Unique

الطريقة الثانية تعتمد على قفل الفرادة. عند إضافة مهمة باستخدام الخيار Unique، سيقوم الـ Client بالتحقق مما إذا كان بإمكانه الحصول على القفل للمهمة المحددة. سيتم إضافة المهمة فقط إذا كان بإمكانه الحصول على القفل. إذا كانت مهمة أخرى تحمل بالفعل القفل، فسوف يقوم الـ Client بإرجاع خطأ (انظر إلى رمز المثال أدناه حول كيفية التحقق من الأخطاء).

يتم ربط قفل الفرادة بمدة صلاحية (وقت ليتم العيش) لتجنب الاحتفاظ بالقفل بشكل دائم. سيتم إطلاق القفل بعد انقضاء المدة الزمنية أو بعد معالجة المهمة بنجاح قبل انقضاء المدة الزمنية.

شيء مهم يجب ملاحظته هنا هو أن ميزة المهمة الفريدة في Asynq تعتمد على أفضل الجهود للحفظ من التكرار. بمعنى آخر، إذا انتهت صلاحية القفل قبل معالجة المهمة، قد يتم إضافة مهمة مكررة.

فرادة المهمة تعتمد على السمات التالية:

  • النوع
  • الحمولة
  • الطابور

لذا، إذا كانت هناك مهام بنفس النوع والحمولة مُضافة إلى نفس الطابور، فإنه لن يتم إضافة مهمة أخرى تحمل نفس السمات حتى يتم إطلاق القفل.

c := asynq.NewClient(redis)

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

// سيحمل t1 قفل الفرادة للساعة القادمة.
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 للتحقق من قيمة الخطأ المُرجعة لتحديد ما إذا كانت تُلف خطأ asynq.ErrDuplicateTask.