Current section

Files

Jump to
glimit src glimit@rate_limiter.erl
Raw

src/glimit@rate_limiter.erl

-module(glimit@rate_limiter).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/glimit/rate_limiter.gleam").
-export([new/2, shutdown/1, hit/1, has_full_bucket/1, set_now/2]).
-export_type([state/0, message/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(false).
-type state() :: {state,
integer(),
integer(),
integer(),
gleam@option:option(integer()),
gleam@option:option(integer())}.
-type message() :: shutdown |
{hit, gleam@erlang@process:subject({ok, nil} | {error, nil})} |
{has_full_bucket, gleam@erlang@process:subject(boolean())} |
{set_now, integer()}.
-file("src/glimit/rate_limiter.gleam", 33).
?DOC(false).
-spec refill_bucket(state()) -> state().
refill_bucket(State) ->
Now@1 = case erlang:element(6, State) of
none ->
glimit@utils:now();
{some, Now} ->
Now
end,
Time_diff = case erlang:element(5, State) of
none ->
0;
{some, Last_update} ->
Now@1 - Last_update
end,
Token_count = begin
_pipe = erlang:element(4, State) + (erlang:element(3, State) * Time_diff),
_pipe@1 = gleam@int:min(_pipe, erlang:element(2, State)),
gleam@int:max(_pipe@1, 0)
end,
{state,
erlang:element(2, State),
erlang:element(3, State),
Token_count,
{some, Now@1},
erlang:element(6, State)}.
-file("src/glimit/rate_limiter.gleam", 52).
?DOC(false).
-spec remove_token(state()) -> state().
remove_token(State) ->
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State) - 1,
erlang:element(5, State),
erlang:element(6, State)}.
-file("src/glimit/rate_limiter.gleam", 78).
?DOC(false).
-spec handle_message(state(), message()) -> gleam@otp@actor:next(state(), message()).
handle_message(State, Message) ->
case Message of
shutdown ->
gleam@otp@actor:stop();
{hit, Client} ->
State@1 = refill_bucket(State),
{Result, State@2} = case erlang:element(4, State@1) of
0 ->
{{error, nil}, State@1};
_ ->
{{ok, nil}, remove_token(State@1)}
end,
gleam@otp@actor:send(Client, Result),
gleam@otp@actor:continue(State@2);
{has_full_bucket, Client@1} ->
State@3 = refill_bucket(State),
Result@1 = erlang:element(4, State@3) =:= erlang:element(2, State@3),
gleam@otp@actor:send(Client@1, Result@1),
gleam@otp@actor:continue(State@3);
{set_now, Now} ->
gleam@otp@actor:continue(
{state,
erlang:element(2, State),
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State),
{some, Now}}
)
end.
-file("src/glimit/rate_limiter.gleam", 107).
?DOC(false).
-spec new(integer(), integer()) -> {ok, gleam@erlang@process:subject(message())} |
{error, nil}.
new(Max_token_count, Token_rate) ->
State = {state, Max_token_count, Token_rate, Max_token_count, none, none},
_pipe = gleam@otp@actor:new(State),
_pipe@1 = gleam@otp@actor:on_message(_pipe, fun handle_message/2),
_pipe@2 = gleam@otp@actor:start(_pipe@1),
_pipe@3 = gleam@result:map(
_pipe@2,
fun(Started) -> erlang:element(3, Started) end
),
gleam@result:map_error(_pipe@3, fun(_) -> nil end).
-file("src/glimit/rate_limiter.gleam", 128).
?DOC(false).
-spec shutdown(gleam@erlang@process:subject(message())) -> nil.
shutdown(Rate_limiter) ->
gleam@otp@actor:send(Rate_limiter, shutdown).
-file("src/glimit/rate_limiter.gleam", 134).
?DOC(false).
-spec hit(gleam@erlang@process:subject(message())) -> {ok, nil} | {error, nil}.
hit(Rate_limiter) ->
gleam@otp@actor:call(Rate_limiter, 10, fun(Field@0) -> {hit, Field@0} end).
-file("src/glimit/rate_limiter.gleam", 140).
?DOC(false).
-spec has_full_bucket(gleam@erlang@process:subject(message())) -> boolean().
has_full_bucket(Rate_limiter) ->
gleam@otp@actor:call(
Rate_limiter,
10,
fun(Field@0) -> {has_full_bucket, Field@0} end
).
-file("src/glimit/rate_limiter.gleam", 146).
?DOC(false).
-spec set_now(gleam@erlang@process:subject(message()), integer()) -> nil.
set_now(Rate_limiter, Now) ->
gleam@otp@actor:send(Rate_limiter, {set_now, Now}).