2020-10-14 09:09:26 +00:00
|
|
|
-module(ct_stash).
|
2021-02-04 14:23:35 +00:00
|
|
|
|
2020-10-14 09:09:26 +00:00
|
|
|
-behaviour(gen_server).
|
|
|
|
|
|
|
|
-export([start/0]).
|
|
|
|
-export([destroy/1]).
|
|
|
|
-export([append/3]).
|
|
|
|
-export([flush/2]).
|
|
|
|
|
|
|
|
-export([
|
|
|
|
init/1,
|
|
|
|
handle_call/3,
|
|
|
|
handle_cast/2,
|
|
|
|
handle_info/2,
|
|
|
|
terminate/2,
|
|
|
|
code_change/3
|
|
|
|
]).
|
|
|
|
|
|
|
|
-define(CALL_TIMEOUT, 1000).
|
|
|
|
|
|
|
|
%%% API
|
|
|
|
|
|
|
|
-type key() :: _.
|
|
|
|
-type entry() :: _.
|
|
|
|
|
2021-02-04 14:23:35 +00:00
|
|
|
-spec start() -> {ok, pid()}.
|
2020-10-14 09:09:26 +00:00
|
|
|
start() ->
|
|
|
|
gen_server:start(?MODULE, [], []).
|
|
|
|
|
2021-02-04 14:23:35 +00:00
|
|
|
-spec destroy(pid()) -> ok | {error, {nonempty, _Left :: #{key() => entry()}}}.
|
2020-10-14 09:09:26 +00:00
|
|
|
destroy(Pid) ->
|
|
|
|
call(Pid, destroy).
|
|
|
|
|
2021-02-04 14:23:35 +00:00
|
|
|
-spec append(pid(), key(), entry()) -> ok.
|
2020-10-14 09:09:26 +00:00
|
|
|
append(Pid, Key, Entry) ->
|
|
|
|
call(Pid, {append, Key, Entry}).
|
|
|
|
|
2021-02-04 14:23:35 +00:00
|
|
|
-spec flush(pid(), key()) -> {ok, [entry()]} | error.
|
2020-10-14 09:09:26 +00:00
|
|
|
flush(Pid, Key) ->
|
|
|
|
call(Pid, {flush, Key}).
|
|
|
|
|
|
|
|
call(Pid, Msg) ->
|
|
|
|
gen_server:call(Pid, Msg, ?CALL_TIMEOUT).
|
|
|
|
|
|
|
|
%%% gen_server callbacks
|
|
|
|
|
2022-02-21 08:56:58 +00:00
|
|
|
-spec init(term()) -> {ok, map()}.
|
2020-10-14 09:09:26 +00:00
|
|
|
init(_) ->
|
|
|
|
{ok, #{}}.
|
|
|
|
|
2022-02-21 08:56:58 +00:00
|
|
|
-spec handle_call(term(), {pid(), term()}, term()) -> {reply, term(), term()}.
|
2020-10-14 09:09:26 +00:00
|
|
|
handle_call({append, Key, Entry}, _From, State) ->
|
|
|
|
Entries = maps:get(Key, State, []),
|
|
|
|
State1 = maps:put(Key, [Entry | Entries], State),
|
|
|
|
{reply, ok, State1};
|
|
|
|
handle_call({flush, Key}, _From, State) ->
|
|
|
|
case maps:take(Key, State) of
|
|
|
|
{Entries, State1} ->
|
|
|
|
{reply, {ok, lists:reverse(Entries)}, State1};
|
|
|
|
error ->
|
|
|
|
{reply, error, State}
|
|
|
|
end;
|
|
|
|
handle_call(destroy, _From, State) ->
|
|
|
|
case maps:size(State) of
|
|
|
|
0 ->
|
|
|
|
{stop, shutdown, ok, State};
|
|
|
|
_ ->
|
2021-02-04 14:23:35 +00:00
|
|
|
Left = maps:map(fun(_, Entries) -> lists:reverse(Entries) end, State),
|
2020-10-14 09:09:26 +00:00
|
|
|
Reason = {error, {nonempty, Left}},
|
|
|
|
{stop, Reason, Reason, State}
|
|
|
|
end.
|
|
|
|
|
2021-02-04 14:23:35 +00:00
|
|
|
-spec handle_cast(term(), atom()) -> {noreply, atom()}.
|
2020-10-14 09:09:26 +00:00
|
|
|
handle_cast(_Msg, State) ->
|
|
|
|
{noreply, State}.
|
|
|
|
|
|
|
|
-spec handle_info(term(), atom()) -> {noreply, atom()}.
|
|
|
|
handle_info(_Info, State) ->
|
|
|
|
{noreply, State}.
|
|
|
|
|
|
|
|
-spec terminate(term(), atom()) -> atom().
|
|
|
|
terminate(_Reason, _State) ->
|
|
|
|
ok.
|
|
|
|
|
|
|
|
-spec code_change(term(), term(), term()) -> {ok, atom()}.
|
|
|
|
code_change(_OldVsn, State, _Extra) ->
|
|
|
|
{ok, State}.
|