Current section
Files
Jump to
Current section
Files
src/pig@session_store@memory.erl
-module(pig@session_store@memory).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/pig/session_store/memory.gleam").
-export([start/1, snapshot/1, store/1, stop/1]).
-export_type([memory_store/0, store_message/0, state/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(" In-memory, actor-serialized implementation of the synchronous session store.\n").
-opaque memory_store() :: {memory_store,
gleam@erlang@process:subject(store_message())}.
-type store_message() :: {commit,
pig@session_store:session_commit(),
gleam@erlang@process:subject({ok, pig@session_store:session()} |
{error, pig@session_store:session_error()})} |
{snapshot, gleam@erlang@process:subject(pig@session_store:session())} |
stop.
-type state() :: {state,
pig@session_store:session(),
gleam@dict:dict(binary(), pig@session_store:session_commit())}.
-file("src/pig/session_store/memory.gleam", 82).
-spec apply_commit(state(), pig@session_store:session_commit()) -> {{ok,
pig@session_store:session()} |
{error, pig@session_store:session_error()},
state()}.
apply_commit(State, Next) ->
{session_commit, Id, Parent, Messages} = Next,
case Messages of
[] ->
{{error,
{invalid_commit,
<<"a commit must contain at least one message"/utf8>>}},
State};
_ ->
case gleam_stdlib:map_get(erlang:element(3, State), Id) of
{ok, Previous} ->
case (erlang:element(3, Previous) =:= Parent) andalso (erlang:element(
4,
Previous
)
=:= Messages) of
true ->
{{ok, erlang:element(2, State)}, State};
false ->
{{error,
{corrupt,
<<"commit ID was reused with different contents"/utf8>>}},
State}
end;
{error, _} ->
case Parent =:= erlang:element(2, erlang:element(2, State)) of
false ->
{{error,
{parent_conflict,
Parent,
erlang:element(
2,
erlang:element(2, State)
)}},
State};
true ->
Session = {session,
{some, Id},
lists:append(
erlang:element(3, erlang:element(2, State)),
Messages
)},
{{ok, Session},
{state,
Session,
gleam@dict:insert(
erlang:element(3, State),
Id,
Next
)}}
end
end
end.
-file("src/pig/session_store/memory.gleam", 67).
-spec handle_message(state(), store_message()) -> gleam@otp@actor:next(state(), any()).
handle_message(State, Message) ->
case Message of
{snapshot, Reply_to} ->
gleam@erlang@process:send(Reply_to, erlang:element(2, State)),
gleam@otp@actor:continue(State);
{commit, Next, Reply_to@1} ->
{Result, Next_state} = apply_commit(State, Next),
gleam@erlang@process:send(Reply_to@1, Result),
gleam@otp@actor:continue(Next_state);
stop ->
gleam@otp@actor:stop()
end.
-file("src/pig/session_store/memory.gleam", 29).
?DOC(" Start an in-memory store with `initial` as its durable session.\n").
-spec start(pig@session_store:session()) -> {ok, memory_store()} |
{error, gleam@otp@actor:start_error()}.
start(Initial) ->
Builder = begin
_pipe = gleam@otp@actor:new({state, Initial, maps:new()}),
gleam@otp@actor:on_message(_pipe, fun handle_message/2)
end,
case gleam@otp@actor:start(Builder) of
{ok, Started} ->
{ok, {memory_store, erlang:element(3, Started)}};
{error, Error} ->
{error, Error}
end.
-file("src/pig/session_store/memory.gleam", 59).
-spec commit_session(memory_store(), pig@session_store:session_commit()) -> {ok,
pig@session_store:session()} |
{error, pig@session_store:session_error()}.
commit_session(Handle, Next) ->
{memory_store, Subject} = Handle,
gleam@otp@actor:call(
Subject,
5000,
fun(Reply_to) -> {commit, Next, Reply_to} end
).
-file("src/pig/session_store/memory.gleam", 48).
?DOC(" Return a consistent snapshot of the current session.\n").
-spec snapshot(memory_store()) -> pig@session_store:session().
snapshot(Handle) ->
{memory_store, Subject} = Handle,
gleam@otp@actor:call(Subject, 5000, fun(Field@0) -> {snapshot, Field@0} end).
-file("src/pig/session_store/memory.gleam", 41).
?DOC(" Adapt an in-memory store to the public synchronous session-store contract.\n").
-spec store(memory_store()) -> pig@session_store:session_store().
store(Handle) ->
{session_store,
fun() -> {ok, snapshot(Handle)} end,
fun(Next) -> commit_session(Handle, Next) end}.
-file("src/pig/session_store/memory.gleam", 54).
?DOC(" Stop the store actor.\n").
-spec stop(memory_store()) -> nil.
stop(Handle) ->
{memory_store, Subject} = Handle,
gleam@otp@actor:send(Subject, stop).