شرح نمط قاطع الدائرة (Circuit Breaker) من خلال تجربة فشل

واجهتُ مشكلة غير متوقعة قبل بضعة أيام.

شعرتُ بإحباط شديد. أردتُ إصلاحها، لكن الفضول دفعني للمواصلة.

جلستُ مع المشكلة مرة أخرى، ووجدتُ الحل. يُسمى هذا الحل "قاطع الدائرة" (Circuit Breaker).

في البرمجيات، يمنع قاطع الدائرة فشلاً واحداً من التسبب في انهيار نظامك بالكامل. إنه يعمل تماماً مثل قاطع التيار الكهربائي في منزلك.

يتكون قاطع الدائرة من ثلاث حالات:

  • مغلق (CLOSED): كل شيء يعمل. تمر جميع الطلبات. يقوم النظام بتتبع حالات الفشل. إذا وصل عدد حالات الفشل إلى حد معين، يفتح القاطع.
  • مفتوح (OPEN): يتوقف النظام عن استقبال جميع الطلبات فوراً. هذا يمنح الخدمة المتعثرة وقتاً للتعافي.
  • نصف مفتوح (HALF_OPEN): يسمح النظام ببعض طلبات الاختبار. إذا نجحت، يُغلق القاطع. وإذا فشلت، يُفتح القاطع مرة أخرى.

إليك تطبيق بسيط لهذا النمط في الكود:

export class CircuitBreaker {
    constructor(failureThreshold, cooldownMs) {
        this.failureThreshold = failureThreshold
        this.cooldownMs = cooldownMs
        this.state = "CLOSED"
        this.failureCount = 0
        this.lastFailureTime = null
    }

    openCircuit() {
        this.state = "OPEN"
        this.lastFailureTime = Date.now()
    }

    closeCircuit() {
        this.state = "CLOSED"
        this.failureCount = 0
        this.lastFailureTime = null
    }

    halfOpenCircuit() {
        this.state = "HALF_OPEN"
    }

    async execute(fn) {
        if (this.state === "OPEN") {
            const cooldownExpired = Date.now() - this.lastFailureTime >= this.cooldownMs
            if (!cooldownExpired) {
                throw new Error("Circuit is open.")
            }
            this.halfOpenCircuit();
        }

        try {
            const result = await fn()
            if (this.state === "HALF_OPEN") {
                this.closeCircuit()
            }
            return result;
        } catch (error) {
            if (this.state === "HALF_OPEN") {
                this.openCircuit()
                throw error;
            }
            this.failureCount++
            if (this.failureCount >= this.failureThreshold) {
                this.openCircuit()
            }
            throw error
        }
    }
}

لقد أصلحت هذه الآلية مشكلتي الأخيرة؛ فهي تمنع تدفق الأخطاء من التسبب في انهيار تطبيقك.

يرجى مشاركة آرائكم في التعليقات. ما زلتُ في مرحلة التعلم.

المصدر: https://dev.to/neel-vekariya/circuit-breaker-explained-through-real-failure-experience-3aeg