A simple Circuit Breaker implementation for protecting external API calls.
The circuit breaker has three states:
:closed- Normal operation, requests go through:open- Requests are short-circuited (fail fast):half_open- Testing if the service has recovered
The protected function is executed in the caller process, so slow calls never block the breaker process itself and concurrent calls are not serialized through a single process.
Usage
# Protect an API call
result =
SuperWorker.CircuitBreaker.call(:my_external_service, fn ->
HTTPoison.get("https://api.example.com/data")
end)
case result do
{:ok, response} -> # Handle success
{:error, :circuit_open} -> # Handle circuit open
{:error, reason} -> # Handle other errors
endWhen the call that trips the threshold fails, the real error is returned;
all subsequent calls fail fast with {:error, :circuit_open} until the
reset timeout elapses.
Summary
Functions
Call a function protected by the circuit breaker.
Returns a specification to start this module under a supervisor.
Get the current state of the circuit breaker.
Reset the circuit breaker to closed state.
Start a circuit breaker for a named service.
Types
@type t() :: %SuperWorker.CircuitBreaker{ failure_count: non_neg_integer(), failure_threshold: pos_integer(), half_open_max_calls: pos_integer(), in_flight: non_neg_integer(), last_failure_time: integer() | nil, name: atom(), reset_timeout: pos_integer(), state: :closed | :open | :half_open, success_count: non_neg_integer() }
Functions
Call a function protected by the circuit breaker.
The function runs in the caller process; the breaker only tracks the
outcome. Exceptions and exits inside fun are converted to error tuples.
Returns a specification to start this module under a supervisor.
See Supervisor.
Get the current state of the circuit breaker.
@spec reset(atom()) :: :ok | {:error, :not_found}
Reset the circuit breaker to closed state.
Start a circuit breaker for a named service.
The breaker process is linked to the caller.