المستوى المطلوب: متوسط — لازم تعرف Node.js و async/await، ويفضّل تكون شفت Microservices أو API Calls بين خدمات قبل كده.
لو الـ Payment Service بتاعك بطئت من 80ms لـ 4 ثواني، خدمة الـ Checkout اللي بتنادي عليها هتبدأ تخزّن طلبات معلّقة، وفي 30 ثانية الـ Memory هيتفجّر، وكل الموقع هيسقط — مش بس الـ Payment. ده اللي اسمه cascading failure. Circuit Breaker بيمنع ده بكام سطر كود، والمقال ده هيعدّيك من المثال البسيط للكود الإنتاجي الكامل.
اعمل Circuit Breaker لـ API Calls بـ Node.js يحمي خدمتك من السقوط المتسلسل
المشكلة باختصار
أي تطبيق فيه أكتر من خدمة بتنادي بعض، أو بيعتمد على API خارجي زي Stripe و SendGrid و OpenAI، عرضة لمشكلة واحدة محددة: الخدمة الخارجية بتبطّأ، مش بتسقط. الطلبات عندك بتفضل مفتوحة بتستنى رد. كل request مفتوح بياخد socket، وذاكرة، وحصته من event loop. في خلال دقيقتين، خدمتك انت — اللي المفروض شغّالة — بتسقط لأنها استنفدت كل الـ connections. ده مش سقوط الخدمة الخارجية. ده سقوطك انت بسبب فشل في حد تاني.
مثال للمبتدئين: قاطع الكهربا في البيت
تخيّل البيت بتاعك. لو حصل short circuit في الفرن، قاطع الكهربا بيفصل التيار عن الفرن خلال جزء من الثانية. لو القاطع مكانش موجود، الحرارة كانت هتسري في الأسلاك وتولّع الجدار كله. القاطع بيعمل تلات حاجات بالظبط: بيكتشف المشكلة، بيقطع الدايرة، وبعد ما المالك يصلّح المشكلة بيرجّع التيار يدوي. Circuit Breaker في الكود بيعمل نفس التلات حاجات، بس مع API calls بدل الكهربا، وبيرجّع نفسه تلقائيًا بدون تدخّل بشري.
التعريف العلمي: الحالات الثلاث
Circuit Breaker بيشتغل كآلة حالات (state machine) بتلات حالات. الفهم الدقيق ليهم هو اللي بيحدّد إعداداته صح:
- Closed: الحالة الافتراضية. الطلبات بتعدي للخدمة الخارجية عادي. القاطع بيعدّ نسبة الفشل في نافذة زمنية (sliding window). لو نسبة الفشل عدّت threshold معيّن (مثلاً 50% من آخر 20 طلب) خلال دقيقة، القاطع بينقل لـ Open.
- Open: القاطع مفتوح، يعني الدايرة مفصولة. أي طلب جديد بيرجع فورًا بـ error مخصّص (CircuitBreakerOpenError) من غير ما يلمس الشبكة أصلاً. ده بيوفّر وقت كل request وبيحرّر الـ connections. القاطع بيفضل Open لمدة ثابتة (reset timeout)، شائع 30 ثانية.
- Half-Open: بعد reset timeout، القاطع بيسمح بعدد محدود من الطلبات (مثلاً 3) يعدّوا فعلاً للخدمة. لو نجحوا كلهم، القاطع بيرجع Closed. لو فشل أي واحد، بيرجع Open ويفضل تاني فترة الـ timeout كاملة.
الحل: تنفيذ بـ Node.js في 60 سطر
هنستخدم مكتبة opossum اللي هي إصدار Node.js المُلهم من Hystrix بتاع Netflix. هي battle-tested ومستخدمة في IBM وعدد كبير من شركات الإنتاج. التركيب مباشر: