Current section

Files

Jump to
glimit src glimit@memory_store.erl
Raw

src/glimit@memory_store.erl

-module(glimit@memory_store).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/glimit/memory_store.gleam").
-export([new/2, get_count/1, remove/2, sweep/3]).
-export_type([memory_store/0, state/0, msg/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).
-opaque memory_store() :: {memory_store, gleam@erlang@process:subject(msg())}.
-type state() :: {state,
gleam@dict:dict(binary(), glimit@bucket:bucket_state()),
gleam@option:option(integer()),
integer(),
gleam@erlang@process:subject(msg())}.
-type msg() :: {get,
binary(),
gleam@erlang@process:subject({ok,
gleam@option:option(glimit@bucket:bucket_state())} |
{error, nil})} |
{set,
binary(),
glimit@bucket:bucket_state(),
integer(),
gleam@erlang@process:subject({ok, nil} | {error, nil})} |
{lock, binary(), gleam@erlang@process:subject({ok, nil} | {error, nil})} |
{unlock, binary(), gleam@erlang@process:subject({ok, nil} | {error, nil})} |
{sweep,
integer(),
gleam@option:option(integer()),
gleam@erlang@process:subject(nil)} |
sweep_timer |
{get_count, gleam@erlang@process:subject(integer())} |
{remove, binary(), gleam@erlang@process:subject(nil)}.
-file("src/glimit/memory_store.gleam", 175).
?DOC(false).
-spec is_idle(
glimit@bucket:bucket_state(),
integer(),
gleam@option:option(integer())
) -> boolean().
is_idle(B, Now, Max_idle_ms) ->
case Max_idle_ms of
none ->
false;
{some, Threshold} ->
case erlang:element(5, B) of
none ->
true;
{some, Last_update} ->
(Now - Last_update) > Threshold
end
end.
-file("src/glimit/memory_store.gleam", 164).
?DOC(false).
-spec do_sweep(
gleam@dict:dict(binary(), glimit@bucket:bucket_state()),
integer(),
gleam@option:option(integer())
) -> gleam@dict:dict(binary(), glimit@bucket:bucket_state()).
do_sweep(Data, Now, Max_idle_ms) ->
_pipe = Data,
gleam@dict:filter(
_pipe,
fun(_, B) ->
not glimit@bucket:is_full(B, Now) andalso not is_idle(
B,
Now,
Max_idle_ms
)
end
).
-file("src/glimit/memory_store.gleam", 186).
?DOC(false).
-spec schedule_sweep(state()) -> nil.
schedule_sweep(State) ->
_ = gleam@erlang@process:send_after(
erlang:element(5, State),
erlang:element(4, State),
sweep_timer
),
nil.
-file("src/glimit/memory_store.gleam", 111).
?DOC(false).
-spec handle_message(state(), msg()) -> gleam@otp@actor:next(state(), msg()).
handle_message(State, Msg) ->
case Msg of
{get, Key, Reply} ->
Result = case gleam_stdlib:map_get(erlang:element(2, State), Key) of
{ok, B} ->
{ok, {some, B}};
{error, _} ->
{ok, none}
end,
gleam@otp@actor:send(Reply, Result),
gleam@otp@actor:continue(State);
{set, Key@1, Bucket_state, _, Reply@1} ->
Data = gleam@dict:insert(
erlang:element(2, State),
Key@1,
Bucket_state
),
gleam@otp@actor:send(Reply@1, {ok, nil}),
gleam@otp@actor:continue(
{state,
Data,
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State)}
);
{lock, _, Reply@2} ->
gleam@otp@actor:send(Reply@2, {ok, nil}),
gleam@otp@actor:continue(State);
{unlock, _, Reply@3} ->
gleam@otp@actor:send(Reply@3, {ok, nil}),
gleam@otp@actor:continue(State);
{sweep, Now, Max_idle_ms, Reply@4} ->
Data@1 = do_sweep(erlang:element(2, State), Now, Max_idle_ms),
gleam@otp@actor:send(Reply@4, nil),
gleam@otp@actor:continue(
{state,
Data@1,
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State)}
);
sweep_timer ->
Now@1 = glimit@utils:now(),
Data@2 = do_sweep(
erlang:element(2, State),
Now@1,
erlang:element(3, State)
),
schedule_sweep(State),
gleam@otp@actor:continue(
{state,
Data@2,
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State)}
);
{get_count, Reply@5} ->
gleam@otp@actor:send(Reply@5, maps:size(erlang:element(2, State))),
gleam@otp@actor:continue(State);
{remove, Key@2, Reply@6} ->
Data@3 = gleam@dict:delete(erlang:element(2, State), Key@2),
gleam@otp@actor:send(Reply@6, nil),
gleam@otp@actor:continue(
{state,
Data@3,
erlang:element(3, State),
erlang:element(4, State),
erlang:element(5, State)}
)
end.
-file("src/glimit/memory_store.gleam", 90).
?DOC(false).
-spec make_store(gleam@erlang@process:subject(msg())) -> glimit@bucket:store().
make_store(Subject) ->
{store,
fun(Key) ->
_pipe = glimit@utils:safe_call(
Subject,
fun(_capture) -> {get, Key, _capture} end,
1000
),
gleam@result:flatten(_pipe)
end,
fun(Key@1, State, Ttl) ->
_pipe@1 = glimit@utils:safe_call(
Subject,
fun(_capture@1) -> {set, Key@1, State, Ttl, _capture@1} end,
1000
),
gleam@result:flatten(_pipe@1)
end,
fun(_) -> {ok, nil} end,
fun(_) -> {ok, nil} end}.
-file("src/glimit/memory_store.gleam", 55).
?DOC(false).
-spec new(gleam@option:option(integer()), integer()) -> {ok,
{glimit@bucket:store(), memory_store()}} |
{error, nil}.
new(Max_idle_ms, Sweep_interval_ms) ->
Start_result = begin
_pipe@1 = gleam@otp@actor:new_with_initialiser(
1000,
fun(Self_subject) ->
State = {state,
maps:new(),
Max_idle_ms,
Sweep_interval_ms,
Self_subject},
schedule_sweep(State),
{ok,
begin
_pipe = gleam@otp@actor:initialised(State),
gleam@otp@actor:returning(_pipe, Self_subject)
end}
end
),
_pipe@2 = gleam@otp@actor:on_message(_pipe@1, fun handle_message/2),
gleam@otp@actor:start(_pipe@2)
end,
case Start_result of
{ok, Started} ->
Subject = erlang:element(3, Started),
Store = make_store(Subject),
Handle = {memory_store, Subject},
{ok, {Store, Handle}};
{error, _} ->
{error, nil}
end.
-file("src/glimit/memory_store.gleam", 194).
?DOC(false).
-spec get_count(memory_store()) -> integer().
get_count(Store) ->
_pipe = glimit@utils:safe_call(
erlang:element(2, Store),
fun(Field@0) -> {get_count, Field@0} end,
1000
),
gleam@result:unwrap(_pipe, 0).
-file("src/glimit/memory_store.gleam", 201).
?DOC(false).
-spec remove(memory_store(), binary()) -> {ok, nil} | {error, nil}.
remove(Store, Key) ->
glimit@utils:safe_call(
erlang:element(2, Store),
fun(_capture) -> {remove, Key, _capture} end,
1000
).
-file("src/glimit/memory_store.gleam", 207).
?DOC(false).
-spec sweep(memory_store(), integer(), gleam@option:option(integer())) -> {ok,
nil} |
{error, nil}.
sweep(Store, Now, Max_idle_ms) ->
glimit@utils:safe_call(
erlang:element(2, Store),
fun(_capture) -> {sweep, Now, Max_idle_ms, _capture} end,
1000
).