Reputation: 691
I need to send a message to a globally registered process, that might be unavailable for a short-time, when it is replaced with a backup process (i.e. failover).
Is the following snippet good Erlang code:
% send message to globally registered process, with possibility to retry once
send_message(To, Message, Retry) ->
try global:send(To, Message)
catch
% registered process To is unavailable
exit: {badarg, {To, Message}} ->
io:format("catch: exit: {badarg,{~w, ~w}}~n", [To, Message]), % dbg only
case Retry of
true ->
% retry sending message, after 1 second
sleep(1000),
send_message(To, Message, false);
false ->
% re-throw caught exit, including stack trace
erlang:raise(exit, {badarg, {To, Message}},
erlang:get_stacktrace())
end
end.
The Retry parameter is either true or false, indicating the message should be retried once if there was a problem. If the message can still not be sent, I want the same exception to be raised as would have been the case by calling global:send(To, Message) outside a try-catch block.
I know the above works, but I am concerned whether the false section of my case block is good erlang (e.g. using erlang:raise() and rlang:get_stacktrace()).
Any thoughts or suggestions to make the code "better"?
Upvotes: 1
Views: 993
Reputation: 185902
Make two different calls to global:send
, one inside a try ... catch
, the other not:
send_message(To, Message, 0, _, _) ->
global:send(To, Message);
send_message(To, Message, RetriesLeft, RetryDelayMs, MaxRetryDelayMs) ->
try
global:send(To, Message)
catch
% registered process To is unavailable
exit: {badarg, {To, Message}} ->
io:format("catch: exit: {badarg,{~w, ~w}}~n", [To, Message]), % dbg only
% retry after RetryDelayMs milliseconds
sleep(min(RetryDelayMs, MaxRetryDelayMs)),
send_message(To, Message, RetriesLeft - 1, 2 * RetryDelayMs, MaxRetryDelayMs)
end.
EDIT: Added exponential back-off. Be like … nope, just can't do it.
Upvotes: 9
Reputation: 20916
I would do
erlang:error({badarg,{To,Message}})
instead. No real difference as this also generates a stack trace but I think it is clearer. erlang:raise/3
is better for a more generic usage and if you want do things with the stacktrace.
Upvotes: 1