Current section
Files
Jump to
Current section
Files
src/glimit.erl
-module(glimit).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([new/0, per_second/2, burst_limit/2, on_limit_exceeded/2, identifier/2, try_build/1, build/1, apply/2]).
-export_type([rate_limiter/3, rate_limiter_builder/3]).
-type rate_limiter(HVP, HVQ, HVR) :: {rate_limiter,
gleam@erlang@process:subject(glimit@registry:message(HVR)),
fun((HVP) -> HVQ),
fun((HVP) -> HVR)}.
-type rate_limiter_builder(HVS, HVT, HVU) :: {rate_limiter_builder,
gleam@option:option(integer()),
gleam@option:option(integer()),
gleam@option:option(fun((HVS) -> HVU)),
gleam@option:option(fun((HVS) -> HVT))}.
-spec new() -> rate_limiter_builder(any(), any(), any()).
new() ->
{rate_limiter_builder, none, none, none, none}.
-spec per_second(rate_limiter_builder(HWB, HWC, HWD), integer()) -> rate_limiter_builder(HWB, HWC, HWD).
per_second(Limiter, Limit) ->
erlang:setelement(2, Limiter, {some, Limit}).
-spec burst_limit(rate_limiter_builder(HWK, HWL, HWM), integer()) -> rate_limiter_builder(HWK, HWL, HWM).
burst_limit(Limiter, Burst_limit) ->
erlang:setelement(3, Limiter, {some, Burst_limit}).
-spec on_limit_exceeded(rate_limiter_builder(HWT, HWU, HWV), fun((HWT) -> HWU)) -> rate_limiter_builder(HWT, HWU, HWV).
on_limit_exceeded(Limiter, On_limit_exceeded) ->
erlang:setelement(5, Limiter, {some, On_limit_exceeded}).
-spec identifier(rate_limiter_builder(HXC, HXD, HXE), fun((HXC) -> HXE)) -> rate_limiter_builder(HXC, HXD, HXE).
identifier(Limiter, Identifier) ->
erlang:setelement(4, Limiter, {some, Identifier}).
-spec try_build(rate_limiter_builder(HXU, HXV, HXW)) -> {ok,
rate_limiter(HXU, HXV, HXW)} |
{error, binary()}.
try_build(Config) ->
gleam@result:'try'(case erlang:element(2, Config) of
{some, Per_second} ->
{ok, Per_second};
none ->
{error, <<"`per_second` rate limit is required"/utf8>>}
end, fun(Per_second@1) ->
Burst_limit@1 = case erlang:element(3, Config) of
{some, Burst_limit} ->
Burst_limit;
none ->
Per_second@1
end,
gleam@result:'try'(
begin
_pipe = glimit@registry:new(Per_second@1, Burst_limit@1),
gleam@result:map_error(
_pipe,
fun(_) ->
<<"Failed to start rate limiter registry"/utf8>>
end
)
end,
fun(Rate_limiter_registry) ->
gleam@result:'try'(case erlang:element(4, Config) of
{some, Identifier} ->
{ok, Identifier};
none ->
{error,
<<"`identifier` function is required"/utf8>>}
end, fun(Identifier@1) ->
gleam@result:'try'(case erlang:element(5, Config) of
{some, On_limit_exceeded} ->
{ok, On_limit_exceeded};
none ->
{error,
<<"`on_limit_exceeded` function is required"/utf8>>}
end, fun(On_limit_exceeded@1) ->
{ok,
{rate_limiter,
Rate_limiter_registry,
On_limit_exceeded@1,
Identifier@1}}
end)
end)
end
)
end).
-spec build(rate_limiter_builder(HXL, HXM, HXN)) -> rate_limiter(HXL, HXM, HXN).
build(Config) ->
case try_build(Config) of
{ok, Limiter} ->
Limiter;
{error, Message} ->
erlang:error(#{gleam_error => panic,
message => Message,
module => <<"glimit"/utf8>>,
function => <<"build"/utf8>>,
line => 130})
end.
-spec apply(fun((HYF) -> HYG), rate_limiter(HYF, HYG, any())) -> fun((HYF) -> HYG).
apply(Func, Limiter) ->
fun(Input) ->
Identifier = (erlang:element(4, Limiter))(Input),
case begin
_pipe = erlang:element(2, Limiter),
glimit@registry:get_or_create(_pipe, Identifier)
end of
{ok, Rate_limiter} ->
case begin
_pipe@1 = Rate_limiter,
glimit@rate_limiter:hit(_pipe@1)
end of
{ok, nil} ->
Func(Input);
{error, nil} ->
(erlang:element(3, Limiter))(Input)
end;
{error, _} ->
erlang:error(#{gleam_error => panic,
message => <<"Failed to get rate limiter"/utf8>>,
module => <<"glimit"/utf8>>,
function => <<"apply"/utf8>>,
line => 179})
end
end.