View Source TripSwitch (TripSwitch v0.1.3)

TripSwitch is an Elixir implementation of a circuit breaker. The circuit breaker is a popular pattern in softwares that depends on various components/services to keep running.

This library allows you wrap calls (signals) to remote calls in a trip switch. The switch monitors each invocation and records failures, the trip switch gets broken once the recorded failures reaches or surpasses the specified threshold.

signal

Signal

A signal is simple a function that gets invoked. The state of the trip switch gets updated based on the result of this signal, see TripSwitch.Breaker.signal/0.

examples

Examples

iex> TripSwitch.send(id, fn -> {:ok, :good} end)
{:ok, :good}
iex> TripSwitch.send(id, fn -> {:break, :good} end) # record this signal as a failure
{:ok, :good}

Note that a switch only stops invoking a signal after the failure threshold have been reached. In this case, the switch keeps is considered broken until it's repaired.

repairs

Repairs

It's obvious you are asking yourself what you should do when a trip switch gets broken. This library have a concept called Repair. What this means is that a switch is sent for repair automatically once it gets broken. Not all trip switches are considered fixable, you need to specify a repair_time (in milliseconds) when the trip switch is created else you need to manually fix (reset) the trip switch whenever it gets broken.

thresholds

Thresholds

For a trip switch to function correctly, a threshold is needed to be specified. This allows us to define the capacity/expectation of the trip switch. The threshold is specified as a float value, usually between 0 and 1 (ex. 0.2566 or 0.13 and so on).

Simply, a threshold is the percentage of bad signals a trip switch receives before it gets broken and sent for repair.

usage

Usage

To create a trip switch you need to add it to your supervision tree:

children = [{TripSwitch, name: :switch, threshold: 0.5}]

Supervisor.start_link(children, opts)

It supports following options:

  • :name - this will be used as the id for the switch
  • :threshold - the maximum number of thresholds before the switch trips
  • :repair_time - time taken for the switch to get fixed after it gets broken

telemetry

Telemetry

Being a big fan of observability, this library exposes information about it internals using the community approved library (telemetry). You can use the telemetry_poller library to poll these metrics. Below are events that this library publishes.

Below are events published by trip_switch:

  • [:trip_switch, :signal, :start] - dispatched before a given signal is handled

    • Measurement: %{system_time: system_time}
    • Metadata: %{id: atom(), tag: String.t()}
  • [:trip_switch, :signal, :stop] - dispatched after a given signal have been handled

    • Measurement: %{duration: native_time}
    • Metadata: %{id: atom(), tag: String.t()}
  • [:trip_switch, :repair, :start] - dispatched when auto-repair is scheduled

    • Measurement: %{system_time: system_time}
    • Metadata: %{id: atom(), tag: String.t()}
  • [:trip_switch, :repair, :stop] - dispatched after an auto-repair have been completed

    • Measurement: %{duration: native_time}
    • Metadata: %{id: atom(), tag: String.t()}

Link to this section Summary

Functions

Checks if the switch is broken.

Returns a specification to start this module under a supervisor.

Reset the given switch.

Send a signal to the underlying breaker.

Link to this section Functions

@spec broken?(atom()) :: boolean()

Checks if the switch is broken.

A switch is considered broken if the underlying breaker is half_open or open.

examples

Examples

iex> TripSwitch.broken?(:switch)
true
@spec child_spec(keyword()) :: Supervisor.child_spec()

Returns a specification to start this module under a supervisor.

See Supervisor.

@spec reset(atom()) :: :ok

Reset the given switch.

Calling this function on a broken switch returns it to a working state.

examples

Examples

  iex> TripSwitch.reset(:switch)
  :ok
@spec send(atom(), TripSwitch.Breaker.signal()) :: {:ok, term()} | :broken

Send a signal to the underlying breaker.

The signal is a function that performs some actions then return a result that alters the state of the underlying breaker.

examples

Examples

iex> TripSwitch.send(:switch, fn -> {:ok, %{name: "a"}}) end)
{:ok, %{name: "a"}}
iex> TripSwitch.send(:switch, fn -> {:break, {:error, :not_found}} end)
{:error, :not_found}