ExResilience (ex_resilience v0.4.0)

Copy Markdown View Source

Composable resilience middleware for Elixir.

Provides bulkhead, circuit breaker, retry, and rate limiter patterns as independently usable GenServer-based layers that compose into an ordered pipeline.

Standalone Usage

Each pattern can be used on its own:

{:ok, _} = ExResilience.Bulkhead.start_link(name: :http_pool, max_concurrent: 10)
{:ok, response} = ExResilience.Bulkhead.call(:http_pool, fn -> HTTPClient.get(url) end)

Pipeline Usage

pipeline =
  ExResilience.new(:my_service)
  |> ExResilience.add(:bulkhead, max_concurrent: 10)
  |> ExResilience.add(:circuit_breaker, failure_threshold: 5)
  |> ExResilience.add(:retry, max_attempts: 3)

{:ok, _pids} = ExResilience.start(pipeline)
result = ExResilience.call(pipeline, fn -> HTTPClient.get(url) end)

Layers execute in the order added (outermost first). The example above runs: Bulkhead -> Circuit Breaker -> Retry -> function.

Summary

Functions

Adds a layer to the pipeline.

Executes fun through the pipeline layers.

Creates a new pipeline with the given name.

Starts all GenServer-backed layers in the pipeline.

Starts a pipeline supervisor for the given pipeline.

Functions

add(pipeline, layer, opts \\ [])

Adds a layer to the pipeline.

See ExResilience.Pipeline.add/3 for supported layers and options.

Examples

iex> pipeline = ExResilience.new(:svc) |> ExResilience.add(:retry, max_attempts: 2)
iex> length(pipeline.layers)
1

call(pipeline, fun)

@spec call(ExResilience.Pipeline.t(), (-> term())) :: term()

Executes fun through the pipeline layers.

Layers must be started first via start/1.

new(name)

@spec new(atom()) :: ExResilience.Pipeline.t()

Creates a new pipeline with the given name.

The name is used as a prefix for child process names and in telemetry metadata.

Examples

iex> pipeline = ExResilience.new(:my_service)
iex> pipeline.name
:my_service

start(pipeline)

@spec start(ExResilience.Pipeline.t()) :: {:ok, [pid()]}

Starts all GenServer-backed layers in the pipeline.

Returns {:ok, pids}.

start_link(pipeline, opts \\ [])

@spec start_link(
  ExResilience.Pipeline.t(),
  keyword()
) :: Supervisor.on_start()

Starts a pipeline supervisor for the given pipeline.

This is the preferred way to run a pipeline in a supervision tree. For standalone or test usage, see start/1.

Examples

pipeline =
  ExResilience.new(:my_service)
  |> ExResilience.add(:bulkhead, max_concurrent: 10)
  |> ExResilience.add(:circuit_breaker, failure_threshold: 5)

{:ok, sup} = ExResilience.start_link(pipeline)