Пояснення принципу Circuit Breaker на прикладі помилки

Кілька днів тому я зіткнувся з непередбачуваною проблемою.

Я відчував сильне розчарування. Я хотів це виправити. Допитливість змусила мене продовжувати.

Я знову взявся за вирішення проблеми. Я знайшов рішення. Воно називається circuit breaker.

У програмному забезпеченні 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