إذا كان http.Client مشتركًا بالفعل بين طلبات متزامنة، فأبقِ حقل Transport الخاص به مستقرًا. يستطيع الغلاف أن يزامن أي ناقل مكوَّن بالكامل يتلقاه كل جولة لاحقة:

type routeSlot struct {
    mu sync.RWMutex
    current http.RoundTripper
}

func (s *routeSlot) RoundTrip(r *http.Request) (*http.Response, error) {
    s.mu.RLock()
    current := s.current
    s.mu.RUnlock()
    return current.RoundTrip(r)
}

func (s *routeSlot) Set(next http.RoundTripper) {
    s.mu.Lock()
    s.current = next
    s.mu.Unlock()
}

باستخدام net/http وsync، هيّئه قبل نشر العميل:

slot := &routeSlot{current: initialTransport}
client := &http.Client{Transport: slot}

slot.Set(nextTransport)

يجب أن يكون initialTransport وnextTransport غير فارغين (non-nil)، ومكوَّنين بالكامل، وآمنين مع التزامن. ابنِ كل ناقل وكيل قبل نشره، واترك إعداده دون تغيير ما دامت الطلبات تستخدمه.

لا يحمي القفل إلا لقطة المؤشر، لذلك لا يحتفظ الطلب البطيء بقفل التوجيه طوال تبادله الشبكي. الطلب الذي يستخدم اللقطة السابقة يواصل على ذلك الناقل؛ والتبديل لا يعيد تشغيله ولا ينقل اتصاله.

احتفظ بالنواقل القديمة وأحِلها عبر دورة حياة التطبيق المحدودة، مع السماح للعمل الجاري بالانتهاء وإغلاق المجمعات الخاملة عند الاقتضاء. قد يتسبب إعادة التوجيه في RoundTrip آخر بعد التبديل. إذا كان سير عمل كامل يحتاج مسارًا واحدًا، فحدد ذلك المسار عند حدود سير العمل بدلًا من تغيير هذا المحدِّد المشترك في منتصفه.

مقالات ذات صلة