breaker v0.1.0 Breaker

A circuit-breaker wrapped around HTTPotion to make requests to external resources and help your application gracefully fail.

Also defines the %Breaker{} struct which represents a request circuit breaker, used with this module.

Defines a function for each HTTP method (ie Breaker.get()) that returns a Task that will execute the HTTP request (using HTTPotion) and record the response in the circuit breaker.

Summary

Types

t()

A %Breaker{} struct containing information for the circuit

Functions

Make an async DELETE request to the specified path using the given breaker

Checks if the given response is either a %Breaker.OpenCircuitError{}, a timeout, or has a 500 status code

Make an async GET request to the specified path using the given breaker

Make an async HEAD request to the specified path using the given breaker

Make an HTTP(S) request using the specified breaker, using the given method

Create a new circuit-breaker with the given options map

Ask if the circuit is open or not

Make an async OPTIONS request to the specified path using the given breaker

Make an async PATCH request to the specified path using the given breaker

Make an async POST request to the specified path using the given breaker

Make an async PUT request to the specified path using the given breaker

Reset the circuit breaker

Trip the circuit

Types

t()
t() :: %Breaker{headers: [...], status: pid, timeout: number, url: String.t}

A %Breaker{} struct containing information for the circuit.

It holds:

  • url: The base url associated with the breaker.
  • headers: Additional headers to use when making requests.
  • timeout: The time to wait (in ms) before giving up on a request.
  • status: The process containing the circuit breaker’s counts and state.

Functions

delete(circuit, path, options \\ [])
delete(Breaker.t, String.t, []) :: Task.t

Make an async DELETE request to the specified path using the given breaker.

Task returning alias for make_request(circuit, path, :delete, options).

error?(response)

Checks if the given response is either a %Breaker.OpenCircuitError{}, a timeout, or has a 500 status code.

Parameters:

  • response: The response recieved from one of the HTTP method calls.

Examples:

iex> Breaker.error?(%Breaker.OpenCircuitError{})
true

iex> Breaker.error?(%HTTPotion.ErrorResponse{})
true

iex> Breaker.error?(%HTTPotion.Response{status_code: 500})
true

iex> Breaker.error?(%HTTPotion.Response{status_code: 200})
false
get(circuit, path, options \\ [])
get(Breaker.t, String.t, []) :: Task.t

Make an async GET request to the specified path using the given breaker.

Task returning alias for make_request(circuit, path, :get, options).

Examples:

iex> breaker = Breaker.new(%{url: "http://httpbin.org/"})
iex> request = Breaker.get(breaker, "/get")
iex> response = Task.await(request)
iex> response.status_code
200
head(circuit, path, options \\ [])
head(Breaker.t, String.t, []) :: Task.t

Make an async HEAD request to the specified path using the given breaker.

Task returning alias for make_request(circuit, path, :head, options).

make_request(circuit, path, method, options \\ [])
make_request(Breaker.t, String.t, atom, []) ::
  %HTTPotion.Response{body: term, headers: term, status_code: term} |
  %HTTPotion.ErrorResponse{message: term} |
  %Breaker.OpenCircuitError{message: term}

Make an HTTP(S) request using the specified breaker, using the given method.

This function isn’t probably one you would want to use on your own and instead, use the method-specific functions (Breaker.get()). They return Tasks and are async, while this is sync.

Parameters:

  • circuit: The circuit to make the request with.
  • path: The request path, this is add to the circuit’s url.
  • method: An atom specifying the HTTP method, used by HTTPotion.
  • options: Extra options to pass to HTTPotion. The circuit’s timeout and headers are also added to this.

Examples:

iex> breaker = Breaker.new(%{url: "http://httpbin.org/"})
iex> response = Breaker.make_request(breaker, "/get", :get)
iex> response.status_code
200
new(options)
new(%{url: String.t}) :: Breaker.t

Create a new circuit-breaker with the given options map.

Available options are:

  • url: The base url to use for the breaker. This is ideally a single external resource, complete with protocal, domain name, port, and an optional subpath. Required.
  • headers: A keyword list of headers, passed to HTTPotion.
  • timeout: How long to wait until considering the request timed out. Passed to HTTPotion.
  • open: Boolean defining if the circuit is broken. Defaults to false.
  • error_threshold: The percent of requests allowed to fail, as a float. Defaults to 0.05 (5%)
  • window_length: The number of buckets in the health calculation window. Defaults to 10.
  • bucket_length: The number of milliseconds for each bucket. Defaults to 1000, meaning health is caluculated over the past 10 seconds using the defaults.

Examples:

iex> options = %{url: "http://httpbin.org/"}
iex> circuit = Breaker.new(options)
iex> is_map(circuit)
true
iex> circuit.__struct__
Breaker
iex> is_pid(circuit.status)
true
open?(circuit)
open?(Breaker.t) :: boolean

Ask if the circuit is open or not.

Examples:

iex> options = %{url: "http://httpbin.org/"}
iex> circuit = Breaker.new(options)
iex> Breaker.open?(circuit)
false
options(circuit, path, options \\ [])
options(Breaker.t, String.t, []) :: Task.t

Make an async OPTIONS request to the specified path using the given breaker.

Task returning alias for make_request(circuit, path, :options, options).

patch(circuit, path, options \\ [])
patch(Breaker.t, String.t, []) :: Task.t

Make an async PATCH request to the specified path using the given breaker.

Task returning alias for make_request(circuit, path, :patch, options).

post(circuit, path, options \\ [])
post(Breaker.t, String.t, []) :: Task.t

Make an async POST request to the specified path using the given breaker.

Task returning alias for make_request(circuit, path, :post, options).

put(circuit, path, options \\ [])
put(Breaker.t, String.t, []) :: Task.t

Make an async PUT request to the specified path using the given breaker.

Task returning alias for make_request(circuit, path, :put, options).

reset(circuit)
reset(Breaker.t) :: :ok

Reset the circuit breaker.

Examples:

iex> options = %{url: "http://httpbin.org/", open: true}
iex> circuit = Breaker.new(options)
iex> Breaker.open?(circuit)
true
iex> Breaker.reset(circuit)
iex> Breaker.open?(circuit)
false
trip(circuit)
trip(Breaker.t) :: :ok

Trip the circuit.

This sets the “open” status to true and has no effect if the “open” status is already true.

This has the effect of cutting off communications using the circuit and starts the restoration process to test if the external source is healthy.

Examples:

iex> circuit = Breaker.new(%{url: "http://httpbin.org/"})
iex> response = Breaker.get(circuit, "/get") |> Task.await
iex> response.status_code
200
iex> Breaker.trip(circuit)
iex> Breaker.get(circuit, "/get") |> Task.await
%Breaker.OpenCircuitError{message: "circuit is open"}