# `PhoenixMicro.Middleware.CircuitBreaker`
[🔗](https://github.com/iamkanishka/phoenix_micro/blob/v1.0.0/lib/phoenix_micro/middleware/circuit_breaker.ex#L1)

Circuit breaker middleware for consumer message handlers.

Implements the classic three-state machine:

```
CLOSED ──(failures >= threshold)──► OPEN
  ▲                                   │
  │                                 (reset_timeout elapses)
  │                                   ▼
  └──────(probe succeeds)────── HALF_OPEN
```

## States

- **CLOSED** — Normal operation. All messages are processed.
  Failures are counted per fuse. When the failure count reaches
  `:threshold` within `:window_ms`, the breaker trips to OPEN.

- **OPEN** — Circuit is tripped. Messages are rejected immediately
  with `{:error, :circuit_open}` — no downstream calls are made.
  After `:reset_timeout_ms`, the breaker transitions to HALF_OPEN.

- **HALF_OPEN** — Probe state. The next single message is allowed
  through as a test. If it succeeds, the breaker resets to CLOSED.
  If it fails, the breaker returns to OPEN and the timeout restarts.

## Usage

Add to a consumer's middleware list:

    defmodule MyApp.PaymentsConsumer do
      use PhoenixMicro.Consumer

      topic "payments.created"
      middleware [
        {PhoenixMicro.Middleware.CircuitBreaker,
         fuse: :payments_db,
         threshold: 5,
         window_ms: 10_000,
         reset_timeout_ms: 30_000}
      ]

      def handle(message, _ctx), do: MyApp.Repo.insert(...)
    end

## Fuse names

The `:fuse` option names the circuit — multiple consumers can share
a fuse (e.g. `fuse: :payments_db`) so that a downstream failure
opens all of them simultaneously. Defaults to the topic name.

## Storage

State is kept in an ETS table (`:phoenix_micro_circuit_breakers`) owned
by `PhoenixMicro.Middleware.CircuitBreaker.Store`. This process must be
started in your supervision tree, which `PhoenixMicro.Application` does
automatically.

## Telemetry events

- `[:phoenix_micro, :circuit_breaker, :tripped]`   — breaker opened
- `[:phoenix_micro, :circuit_breaker, :reset]`      — breaker closed
- `[:phoenix_micro, :circuit_breaker, :rejected]`   — message rejected (OPEN)
- `[:phoenix_micro, :circuit_breaker, :probe]`      — probe sent (HALF_OPEN)

---

*Consult [api-reference.md](api-reference.md) for complete listing*
