Circuit breaker pattern in Lua
lua-circuit-breaker
provides circuit-breaker functionality like resilience4j i.e. for Java.
Any IO function/method that can fail can be wrapped around lua-circuit-breaker
and can be made to fail fast, leading to improved resiliency and fault tolerance.
CB._before()
. This will return an error if the circuit breaker is in open state otherwise will increment the counter of total_requests by 1.CB._after(CB._generation, ok)
. If ok is true, the success counter is incremented by 1. Otherwise, the failure counter gets incremented by 1.luarocks install lua-circuit-breaker
Clone this repo and run:
luarocks make
--Import Circuit breaker factory.
local circuit_breaker_lib = require "lua-circuit-breaker.factory"
--Create a new instance of the circuit breaker factory. Always set version = 0. This is used for flushing the circuit breakers when the configuration is changed.
local circuit_breakers = circuit_breaker_lib:new()
-- Get a circuit breaker instance from factory. Returns a new instance only if not already created.
local settings = {
version = 1,
window_time = 10,
min_calls_in_window= 20,
failure_percent_threshold= 51,
wait_duration_in_open_state= 15,
wait_duration_in_half_open_state= 120,
half_open_max_calls_in_window= 10,
half_open_min_calls_in_window= 5,
notify = function(name, state)
print(string.format("Breaker [ %s ] state changed to [ %s ]", name, state))
end,
}
local cb, err = circuit_breakers:get_circuit_breaker(
"io_call_x", -- Name of circuit breaker. This should be unique.
"io_calls", -- Used to group certain CB objects into one.
settings,
)
-- Check state of cb. This function returns an error if the state is open or half_open_max_calls_in_window is breached.
local _, err_cb = cb:_before()
if err_cb then
return false, "Circuit breaker open error"
end
local generation = cb._generation
-- Call IO method for which circuit breaking is required.
local res, err_http = makeIOCall()
-- Update the state of the cb based on successful / failure response.
local ok = res and res.status and res.status < 500
cb:_after(generation, ok) -- generation is used to update the counter in the correct time bucket.
Parameter | Default | Type | Required | Description |
---|---|---|---|---|
name | NA | string | true | Name of circuit breaker, this should be unique |
group | “default_group” | string | false | Group to which the CB object will belong |
settings.version | NA | number | true | Maintains version of settings object, changing this will create new CB and flush older CB |
settings.window_time | 10 | number | true | Window size in seconds |
settings.min_calls_in_window | 20 | number | true | Minimum number of calls to be present in the window to start calculation |
settings.failure_percent_threshold | 51 | number | true | % of requests that should fail to open the circuit |
settings.wait_duration_in_open_state | 15 | number | true | Duration(sec) to wait before automatically transitioning from open to half-open state |
settings.wait_duration_in_half_open_state | 120 | number | true | Duration(sec) to wait in half-open state before automatically transitioning to closed state |
settings.half_open_min_calls_in_window | 5 | number | true | Minimum number of calls to be present in the half open state to start calculation |
settings.half_open_max_calls_in_window | 10 | number | true | Maximum calls to allow in half open state |
settings.half_open_to_open | NA | function | false | Overrides transition from half-open to open state |
settings.half_open_to_close | NA | function | false | Overrides transition from half-open to closed state |
settings.closed_to_open | NA | function | false | Overrides transtition from closed to open state |
settings.notify | NA | function | false | Overrides with a custom logger function |
new()
: create a new circuit breaker factoryget_circuit_breaker(name, group, settings)
: create a new CB objectcheck_group(group)
: check if this group is presentremove_breakers_by_group(group)
: remove all CB objects in a groupremove_circuit_breaker(name, group)
: remove a particular CB inside a group. if group is not passed, “default_group” is assumed.