Timeouted gen_server:call
Dmitry Belyaev
rumata-estor@REDACTED
Wed May 12 16:48:25 CEST 2010
I have a gen_server and many clients. Clients send request to the server
with gen_server:call(Server, Msg, Timeout) and when timeout occurs they
ask server to abort appropriate reply. But server may reply right before
it receives abort message and I may get trash in client's mailbox.
I'm not sure that client can throw away this trash itself. So it is
possible for client to fill his message queue with lots of such messages.
I may not let client crash. Neither I don't want to spawn new process
for every such request.
Looking through gen module I found that wait_resp*/3 could tell me Mref
with exit({timeout, Mref}). Then I could use gen:call() and catch that
Mref. But it currently doesn't offer such information.
So, I'd like to know how more experienced programmers workaround this
problem.
Code like this:
-export([do_call/4, handle_call/3, handle_info/2]).
do_call(Server, MsgId, Msg, Timeout) ->
try gen_server:call(Server, {process, MsgId, Msg}, Timeout) of
Response ->
Response
catch
exit:{timeout, Reason} ->
%% this is a place when server can reply us
Server ! {abort, MsgId},
%% here I'd like to cleanup message queue but I don't know Mref
error
end.
handle_call({process, MsgId, Msg}, From, State) ->
start_processing(MsgId, Msg),
{noreply, State#state{ids=[{MsgId, From} | State#state.ids]}}.
handle_info({ready, MsgId, Response}, State) ->
case get_from(MsgId, State) of
undefined ->
{noreply, State};
{From, NewState} ->
gen_server:reply(From, Response),
{noreply, NewState}
end;
handle_info({abort, MsgId}, State) ->
case get_from(MsgId, State) of
undefined ->
{noreply, State};
{_, NewState} ->
{noreply, NewState}
end.
More information about the erlang-questions
mailing list