Composable pipeline of resilience layers.
A pipeline is an ordered list of layers that wrap a function call inside-out. The first layer added is the outermost wrapper.
Execution Order
Given layers [bulkhead, circuit_breaker, retry], execution is:
Bulkhead -> Circuit Breaker -> Retry -> functionEach layer wraps the next, so the function sees retry first, then circuit breaker, then bulkhead.
Examples
pipeline = ExResilience.Pipeline.new(:my_pipeline)
|> ExResilience.Pipeline.add(:bulkhead, max_concurrent: 5)
|> ExResilience.Pipeline.add(:circuit_breaker, failure_threshold: 3)
|> ExResilience.Pipeline.add(:retry, max_attempts: 2)
Summary
Functions
Generates a supervised pipeline module.
Adds a layer to the pipeline.
Executes fun through the pipeline layers.
Returns the child process name for a layer in this pipeline.
Creates a new pipeline with the given name.
Starts all GenServer-backed layers in the pipeline.
Sets the error classifier for all layers in the pipeline that support it.
Types
Functions
Generates a supervised pipeline module.
When a module does use ExResilience.Pipeline, it gets:
child_spec/1-- returns a supervisor child specstart_link/1-- starts the pipeline supervisorpipeline/0-- returns the built%Pipeline{}structcall/1-- executes a function through the pipelinecall/2-- executes a function through the pipeline (second arg reserved for future options)
Options
:name-- pipeline name atom. Defaults to the module name converted to an atom.- Layer keys -- any of [:bulkhead, :circuit_breaker, :retry, :rate_limiter, :coalesce, :hedge, :chaos, :fallback, :cache]. Each takes a keyword list of options for that layer. Layers are added in the order specified.
Examples
defmodule MyApp.Resilience do
use ExResilience.Pipeline,
name: :my_service,
bulkhead: [max_concurrent: 10],
circuit_breaker: [failure_threshold: 5],
retry: [max_attempts: 3]
end
# In your supervision tree:
children = [MyApp.Resilience]
Supervisor.start_link(children, strategy: :one_for_one)
# Then call through the pipeline:
MyApp.Resilience.call(fn -> HTTPClient.get(url) end)
Adds a layer to the pipeline.
Layers are executed in the order they are added (outermost first).
Supported Layers
:bulkhead-- seeExResilience.Bulkheadfor options.:circuit_breaker-- seeExResilience.CircuitBreakerfor options.:retry-- seeExResilience.Retryfor options.:rate_limiter-- seeExResilience.RateLimiterfor options.:coalesce-- seeExResilience.Coalescefor options. Requires a:keyoption, either a static term or a 0-arity function returning the key.:hedge-- seeExResilience.Hedgefor options.:chaos-- seeExResilience.Chaosfor options.:fallback-- seeExResilience.Fallbackfor options.:cache-- seeExResilience.Cachefor options. Requires a:keyoption, either a static term or a 0-arity function returning the key.:adaptive_concurrency-- seeExResilience.AdaptiveConcurrencyfor options.
Executes fun through the pipeline layers.
Layers must be started first via start/1 or individually.
Returns the child process name for a layer in this pipeline.
Creates a new pipeline with the given name.
The name is used as a prefix for child process names and in telemetry metadata.
Starts all GenServer-backed layers in the pipeline.
Returns {:ok, pids} where pids is a list of started process pids.
Layers that don't require a process (like retry) are skipped.
Sets the error classifier for all layers in the pipeline that support it.
Layers that already have an :error_classifier option are not overwritten.
Only :circuit_breaker, :retry, and :fallback layers are affected.
Examples
pipeline = Pipeline.new(:my_pipe)
|> Pipeline.add(:circuit_breaker, failure_threshold: 3)
|> Pipeline.add(:retry, max_attempts: 2)
|> Pipeline.with_classifier(MyApp.Classifier)