breaker v1.0.0 Breaker
A circuit-breaker wrapped around HTTPotion to make requests to external
resources and help your application gracefully fail.
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
Functions
Count a given response in the breaker’s current bucket and sums
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
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
Roll the window, creating a new bucket and possibly pushing out an old one, updating the sum values as necessary
Create a new circuit-breaker with the given options keyword list
Trip the circuit
Types
t() :: %{url: String.t, headers: [...], timeout: number, open: boolean, error_threshold: float, window_length: number, bucket_length: number, sum: %{total: number, errors: number}, window: [%{total: number, errors: number}]}
A Map 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.open: The current state of the breaker.error_threshold: The percent of requests allowed to fail, as a float.window_length: The number of buckets in the health calculation window.bucket_length: The number of milliseconds for each bucket.sum: The current sum of total requests and errors.window: The window of buckets adding up tosum.
Functions
count(pid, %HTTPotion.Response{body: term, headers: term, status_code: term} | %HTTPotion.ErrorResponse{message: term}) :: :ok
Count a given response in the breaker’s current bucket and sums.
Adds the response to the current bucket of the health window, the total sum, and finalizes by recalculating the breaker’s status.
You probably won’t need to use this manually.
This is done automatically when a request is made through this module.
Parameters:
circuit: The pid of the breaker to count in.response: The response received from a request.
Examples:
iex> {:ok, circuit} = Breaker.start_link([url: "http://httpbin.org/"])
iex> Breaker.count(circuit, %HTTPotion.ErrorResponse{})
:ok
Make an async DELETE request to the specified path using the given breaker.
Task returning alias for make_request(circuit, path, :delete, options).
Parameters:
circuit: The breaker to perform the request.path: The path string to append to the end of the breaker’surl.options: Additional options passed to HTTPotion.
error?(%Breaker.OpenCircuitError{message: term} | %HTTPotion.ErrorResponse{message: term} | %HTTPotion.Response{body: term, headers: term, status_code: term}) :: boolean
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
Make an async GET request to the specified path using the given breaker.
Task returning alias for make_request(circuit, path, :get, options).
Parameters:
circuit: The breaker to perform the request.path: The path string to append to the end of the breaker’surl.options: Additional options passed to HTTPotion.
Examples:
iex> {:ok, breaker} = Breaker.start_link([url: "http://httpbin.org/"])
iex> request = Breaker.get(breaker, "/get")
iex> response = Task.await(request)
iex> response.status_code
200
Make an async HEAD request to the specified path using the given breaker.
Task returning alias for make_request(circuit, path, :head, options).
Parameters:
circuit: The breaker to perform the request.path: The path string to append to the end of the breaker’surl.options: Additional options passed to HTTPotion.
make_request(pid, 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’surl.method: An atom specifying the HTTP method, used by HTTPotion.options: Extra options to pass to HTTPotion. The circuit’stimeoutandheadersare also added to this.
Examples:
iex> {:ok, breaker} = Breaker.start_link([url: "http://httpbin.org/"])
iex> response = Breaker.make_request(breaker, "/get", :get)
iex> response.status_code
200
Ask if the circuit is open or not.
Don’t forget, an open circuit is one that is not properly connected and thus does not allow electrons to flow. In this case, it does not allow communication to the external resource. I get this mixed up in my head sometimes.
Parameters:
circuit: The pid of the breaker to check.
Examples:
iex> options = [url: "http://httpbin.org/"]
iex> {:ok, circuit} = Breaker.start_link(options)
iex> Breaker.open?(circuit)
false
Make an async OPTIONS request to the specified path using the given breaker.
Task returning alias for make_request(circuit, path, :options, options).
Parameters:
circuit: The breaker to perform the request.path: The path string to append to the end of the breaker’surl.options: Additional options passed to HTTPotion.
Make an async PATCH request to the specified path using the given breaker.
Task returning alias for make_request(circuit, path, :patch, options).
Parameters:
circuit: The breaker to perform the request.path: The path string to append to the end of the breaker’surl.options: Additional options passed to HTTPotion.
Make an async POST request to the specified path using the given breaker.
Task returning alias for make_request(circuit, path, :post, options).
Parameters:
circuit: The breaker to perform the request.path: The path string to append to the end of the breaker’surl.options: Additional options passed to HTTPotion.
Make an async PUT request to the specified path using the given breaker.
Task returning alias for make_request(circuit, path, :put, options).
Parameters:
circuit: The breaker to perform the request.path: The path string to append to the end of the breaker’surl.options: Additional options passed to HTTPotion.
Reset the circuit breaker.
This sets the “open” status to false and has no effect if the “open” status is already false.
This has the effect of restoring communications using the circuit, but it does not clear any recent unhealthy requests. As such, it could recalculate and trip itself again at the end of the next request or after a roll.
Parameters:
circuit: The pid of the breaker to reset.
Examples:
iex> options = [url: "http://httpbin.org/", open: true]
iex> {:ok, circuit} = Breaker.start_link(options)
iex> Breaker.open?(circuit)
true
iex> Breaker.reset(circuit)
iex> Breaker.open?(circuit)
false
Roll the window, creating a new bucket and possibly pushing out an old one, updating the sum values as necessary.
Parameters:
circuit: The pid of the breaker to roll.
Examples:
iex> options = [url: "http://httpbin.org/", window: [%{total: 1, errors: 0}]]
iex> {:ok, circuit} = Breaker.start_link(options)
iex> Breaker.roll(circuit)
:ok
Create a new circuit-breaker with the given options keyword list.
Parameters:
options: A Keyword list of options, described below.name: The name to register the GenServer.
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 toHTTPotion.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> {:ok, circuit} = Breaker.start_link(options)
iex> is_pid(circuit)
true
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.
Parameters
circuit: The pid of the breaker to trip.
Examples:
iex> {:ok, circuit} = Breaker.start_link([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"}