bouncer/test/ct_stash.erl

88 lines
2.0 KiB
Erlang
Raw Normal View History

-module(ct_stash).
-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() :: _.
-spec start() -> {ok, pid()}.
start() ->
gen_server:start(?MODULE, [], []).
-spec destroy(pid()) -> ok | {error, {nonempty, _Left :: #{key() => entry()}}}.
destroy(Pid) ->
call(Pid, destroy).
-spec append(pid(), key(), entry()) -> ok.
append(Pid, Key, Entry) ->
call(Pid, {append, Key, Entry}).
-spec flush(pid(), key()) -> {ok, [entry()]} | error.
flush(Pid, Key) ->
call(Pid, {flush, Key}).
call(Pid, Msg) ->
gen_server:call(Pid, Msg, ?CALL_TIMEOUT).
%%% gen_server callbacks
-spec init(term()) -> {ok, map()}.
init(_) ->
{ok, #{}}.
-spec handle_call(term(), {pid(), term()}, term()) -> {reply, term(), term()}.
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};
_ ->
Left = maps:map(fun(_, Entries) -> lists:reverse(Entries) end, State),
Reason = {error, {nonempty, Left}},
{stop, Reason, Reason, State}
end.
-spec handle_cast(term(), atom()) -> {noreply, atom()}.
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}.