ExBreak v0.0.4 ExBreak View Source

Provides circuit breaker functionality around function calls

Link to this section Summary

Functions

Call a function using a circuit breaker.

Link to this section Types

Link to this type

opt() View Source
opt() ::
  {:timeout_sec, pos_integer()}
  | {:threshold, pos_integer()}
  | {:match_exception, (any() -> boolean())}
  | {:match_return, (any() -> boolean())}

Link to this section Functions

Link to this function

call(fun, args \\ [], opts \\ []) View Source
call(function(), [any()], opts()) :: any()

Call a function using a circuit breaker.

The first option is the function to call, followed by an optional list of arguments.

If the function succeeds, and does not return an error tuple (in the form {:error, any}), the value returned by the function will be returned.

If the function fails (meaning it returns an {:error, any} tuple), a counter is incremented in a circuit breaker for that function. If the counter meets or exceeds the configured circuit breaker threshold, the breaker for that function is marked as tripped.

If the function fails and the circuit breaker for that function has been marked as tripped (and has not expired), then {:error, :circuit_breaker_tripped} will be returned.

A list of options can be provided as the final argument to call:

  • timeout_sec (default 900) The number of seconds after which a tripped breaker times out and is re-opened
  • threshold (default 10) The number of times an error is permitted before further calls will be ignored and will return an {:error, :circuilt_closed}
  • match_exception (default fn _ -> true end) A function called when an exception is raised during the function call. If it returns true, the breaker trip count is incremented.
  • match_return (defaults to return true when matching {:error, _}) A function called on the return value of the function. If it returns true, the breaker trip count is incremented.

Example

This simple example increments the breaker when the return value is {:error, _}:

iex> ExBreak.call(fn ret -> ret end, [:ok])
:ok

iex> fun = fn -> {:error, :fail} end
iex> ExBreak.call(fun, [], threshold: 2)
{:error, :fail}
iex> ExBreak.call(fun, [], threshold: 2)
{:error, :fail}
iex> ExBreak.call(fun, [], threshold: 2)
{:error, :circuit_breaker_tripped}

In this example, we only increment when the return value is exactly {:error, :bad}:

iex> fun = fn ret -> ret end
iex> opts = [threshold: 2, match_return: fn
...>     {:error, :bad} -> true
...>     _ -> false
...>  end]
iex> ExBreak.call(fun, [{:error, :not_bad}], opts)
{:error, :not_bad}
iex> ExBreak.call(fun, [{:error, :not_bad}], opts)
{:error, :not_bad}
iex> ExBreak.call(fun, [{:error, :not_bad}], opts)
{:error, :not_bad}
iex> ExBreak.call(fun, [{:error, :bad}], opts)
{:error, :bad}
iex> ExBreak.call(fun, [{:error, :bad}], opts)
{:error, :bad}
iex> ExBreak.call(fun, [{:error, :bad}], opts)
{:error, :circuit_breaker_tripped}