اس صفحے میں، میں Handler انٹرفیس کے ڈیزائن کی وضاحت کروں گا۔

آپ جو سرور کو فراہم کرتے ہیں، وہ آپ کے غیر تعیناتی کام کے انتظامی منطق کا باعث ہوتا ہے۔ Handler کی ذمہ داری ہے کہ وہ ایک تسک قبول کرے اور اس کو معاملے کے ساتھ پراسرار کے درخواست کے دوران عمل کرے۔ اگر چیز کی عملیات ناکام ہو جاتی ہے، تو وہ بعد میں تسک دوبارہ کرنے کے ليۓ کسی بھی غلطیوں کی اطلاع دیتی ہے۔

اس انٹرفیس کی تعریف مندرجہ ذیل ہے۔

type Handler interface {
    ProcessTask(context.Context, *Task) error
}

یہ ایک سادہ انٹرفیس ہے، جو ہینڈلر کی ذمہ داریوں کو مختصر میں بیان کرتی ہے۔

اس ہینڈلر انٹرفیس کو مناسب کرنے کی مختلف تراکیب ہیں۔

نیچے دی گئی مثال میں آپنے اپنی سٹرکٹ قسم کو تعینات کرنے کا طریقہ ہے تاسکس کو سنبھالنے کے ليۓ۔

type MyTaskHandler struct {
   // ... fields
}

// ProcessTask ترکیب کو پورا کریں
func (h *MyTaskHandler) ProcessTask(ctx context.Context, t *asynq.Task) error {
   // تاسک سنبھالنے کی منطق
}

آپ انٹرفیس کے ليۓ فنکشن بھی تعریف کرسکتے ہیں، HandlerFunc موصول کی مدد سے۔

func myHandler(ctx context.Context, t *asynq.Task) error {
    // تاسک سنبھالنے کی منطق
}

// h انٹرفیس کو مطمئن کردیتا ہے
h := asynq.HandlerFunc(myHandler)

اکثر مواقع پر، آپ کو داخلی تاسک کی Type کی فہرست کو دیکھنے اور اس کے مطابق سنبھالنے کی ضرورت ہوگی۔

func (h *MyTaskHandler) ProcessTask(ctx context.Context, t *asynq.Task) error {
   switch t.Type() {
   case "type1":
      // نوع1 کو سنبھالیں
   case "type2":
      // نوع2 کو سنبھالیں
   case "typeN":
      // نوعN کو سنبھالیں
   default:
      return fmt.Errorf("غیر متوقع تاسک نوع: %q", t.Type())
   }
}

جیسا کہ آپ دیکھ سکتے ہیں، ایک ہینڈلر کو مختلف ہینڈلر کا جوڑ بنایا جا سکتا ہے۔ نیچے دی گئی مثال میں ہر کیس کو ایک مخصوص ہینڈلر سے سنبھالا جا سکتا ہے۔ یہاں ServeMux قسم کا کردار آتا ہے۔

نوٹ: آپ کو ضرورت نہیں ہے کہ آپ ServeMux قسم کو استعمال کریں۔ پر اس کا ہائی کثرت سے استعمال ہوتا ہے۔
ServeMux کا استعمال کرتے ہوئے، آپ مختلف ہینڈلر رجسٹر کرسکتے ہیں۔ یہ ہر تاسک کی قسم کو رجسٹر شدہ پیٹرن کے ساتھ مماثلت کرے گا اور تاسک کی قریبی پیٹرن کو بلو کرنے والا ہینڈلر بُلائے گا۔

mux := asynq.NewServeMux()
mux.Handle("email:welcome", welcomeEmailHandler) // ہینڈلر رجسٹر کریں
mux.Handle("email:reminder", reminderEmailHandler)
mux.Handle("email:", defaultEmailHandler) // "email:" سے شروع ہونے والے دوسرے تاسک نوعوں کے ليۓ ڈیفالٹ ہینڈلر

میڈلویئر استعمال کرنا

اگر آپ کو درخواست کے پہلے اور/یا بعد میں کچھ کوڈ نافذ کرنے کی ضرورت ہوتی ہے، تو آپ میڈلویئر کی مدد سے اسکو حاصل کر سکتے ہیں۔ میڈلویئر ایک فنکشن ہوتا ہے جو ایک Handler لیتا ہے اور ایک Handler واپس دیتا ہے۔
نیچے ایک مثال ہے جو تسک پراسرار کی شروعات اور ختم ہونے کو ریکارڈ کرنے والا میڈلویئر ہے۔

func loggingMiddleware(h asynq.Handler) asynq.Handler {
    return asynq.HandlerFunc(func(ctx context.Context, t *asynq.Task) error {
        start := time.Now()
        log.Printf("%q کے ليۓ عمل میں لایا گیا", t.Type())
        err := h.ProcessTask(ctx, t)
        if err != nil {
            return err
        }
        log.Printf("%q کے ليۓ عمل مکمل ہوا: گزشتہ وقت = %v", t.Type(), time.Since(start))
        return nil
    })
}

اب آپ اس میڈلویئر کو اپنے ہینڈلر کو “واپس” کرنے کے ليۓ استعمال کرسکتے ہیں۔

myHandler = loggingMiddleware(myHandler)

علاوہ ازیں، اگر آپ ServeMux کا استعمال کررہے ہیں، تو آپ اس طرح سے میڈلویئر فراہم کرسکتے ہیں۔

mux := NewServeMux()
mux.Use(loggingMiddleware)

گروپنگ میڈلویئر

اگر آپ کے پاس ایسی صورتحال ہے جہاں آپ ایک میڈل ویئر کو گروپ کے تمام tasks پر لاگو کرنا چاہتے ہیں، تو آپ اسے مختلف ServeMux instances کو ملا کر حاصل کر سکتے ہیں۔ ایک روک یہ ہے کہ ہر گروپ کے tasks کے ناموں کا ایک ہی پریفکس ہونا چاہئے۔

مثال:
اگر آپ کے پاس اورڈرس کو ہینڈل کرنے کے tasks اور پروڈکٹس کو ہینڈل کرنے کے tasks ہیں، اور آپ چاہتے ہیں کہ تمام “پروڈکٹ” tasks پر مشترک منطق لاگو ہو اور دوسرے مشترک منطق کو تمام “آرڈر” tasks پر لاگو کریں، تو آپ اس طرح سے کر سکتے ہیں:

productHandlers := asynq.NewServeMux()
productHandlers.Use(productMiddleware) // تمام پروڈکٹ tasks پر مشترک منطق لاگو کریں
productHandlers.HandleFunc("product:update", productUpdateTaskHandler)
// ... دیگر "پروڈکٹ" task ہینڈلرز رجسٹر کریں

orderHandlers := asynq.NewServeMux()
orderHandlers.Use(orderMiddleware) // تمام آرڈر tasks پر مشترک منطق لاگو کریں
orderHandlers.HandleFunc("order:refund", orderRefundTaskHandler)
// ... دیگر "آرڈر" task ہینڈلرز رجسٹر کریں

// ٹاپ-لیول ہینڈلر
mux := asynq.NewServeMux()
mux.Use(someGlobalMiddleware) // تمام tasks پر مشترک منطق لاگو کریں
mux.Handle("product:", productHandlers)
mux.Handle("order:", orderHandlers)

if err := srv.Run(mux); err != nil {
    log.Fatal(err)
}