Asynq میں یونیک ٹاسک فیچر یقینی بناتا ہے کہ ریڈس قیو میں صرف ایک ٹاسک ہوگا۔

جب آپ ٹاسکس کو مکرر نہ کرنا چاہتے ہیں اور ڈوپلیکیٹ ٹاسکس سے بچنا چاہتے ہیں تو یہ فیچر بہت مفید ہے۔

جائزہ

Asynq میں ٹاسک یکتائی کو یقینی بنانے کے لئے دو طریقے ہیں۔

  1. TaskID آپشن استعمال کرنا: خود ہی ایک یونیک ٹاسک آئی ڈی پیدا کریں۔
  2. یونیک آپشن استعمال کرنا: Asynq کو ٹاسک کے لئے یکتائی لاک بنانے دیں۔

TaskID آپشن استعمال کرنا

اگر آپ پہلے طریقے کو منتخب کرتے ہیں، تو آپ یقینی بنا سکتے ہیں کہ کسی دی گئی ٹاسک آئی ڈی کے نام پر صرف ایک ٹاسک کسی بھی دیی گئی وقت میں ہوگا۔ اگر آپ ایک ہی ٹاسک آئی ڈی کے ساتھ دوسرا ٹاسک انکیو کرنے کی کوشش کرتے ہیں، تو وہ ایک ErrTaskIDConflict خطا واپس کرے گا۔

// پہلا ٹاسک ٹھیک ہو جانا چاہئے
_, err := client.Enqueue(task, asynq.TaskID("mytaskid"))

// دوسرا ٹاسک ناکام ہو جائے گا، اگر پہلا ٹاسک پروسیس نہیں ہوا ہو تو err میں ErrTaskIDConflict (قدرتی تصورات کے تحت) ہوگا
_, err = client.Enqueue(task, asynq.TaskID("mytaskid"))

یونیک آپشن استعمال کرنا

دوسرا طریقہ یکتائی لاک پر مبنی ہے۔ جب یونیک آپشن کا استعمال کرتے ہوئے ٹاسک کو انکیو کرتے ہیں، تو کلائنٹ چیک کرے گا کہ کیا وہ دی گئی ٹاسک کے لئے لاک حاصل کر سکتا ہے یا نہیں۔ ٹاسک صرف اس صورت انکیو ہوگا جب لاک حاصل کیا جاسکتا ہو۔ اگر کسی دوسرے ٹاسک نے پہلے ہی لاک حاصل کیا ہو تو کلائنٹ ایک خطا واپس کرے گا (نیچے دی گئی مثال کو دیکھنے کے لئے).

یکتائی لاک کو TTL (وقت گزرنے تک جاری رہنے کا وقت) سے منسلک کیا گیا ہے تاکہ یہ لاک دائمی طور پر نہ رہے۔ لاک TTL کے بعد یا اس وقت کے بعد جب تاسک کامیابی سے پروسیس ہو گیا ہو تو لاک کو وقت گزرنے کے بعد چھوڑ دیا جائے گا۔

ایک اہم بات یہ ہے کہ 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 انکیو نہیں کیا جاسکتا چونکہ yeh t1 کا ڈوپلیکیٹ ہے۔
err = c.Enqueue(t2, asynq.Unique(time.Hour))
switch {
case errors.Is(err, asynq.ErrDuplicateTask):
    // ڈوپلیکیٹ ٹاسک کا سامنا کریں
case err != nil:
    // دیگر خطاوں کا سامنا کریں
}

اوپر دی گئی مثال میں، t2 انکیو نہیں کیا جائے گا چونکہ yeh t1 کا ڈوپلیکیٹ ہے۔ آپ errors.Is استعمال کرکے واپس آنے والی error کی قیمت کو چیک کرنے کے لئے asynq.ErrDuplicateTask کو wrap کرتے ہیں۔