Хороший дизайн для повторной отправки сообщения? - PullRequest
1 голос
/ 07 декабря 2010

Мне нужно отправить сообщение глобально зарегистрированному процессу, которое может быть недоступно в течение короткого времени, если оно будет заменено процессом резервного копирования (т. Е. Аварийное переключение).

Является ли следующий фрагмент хорошим Erlangкод:

% 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.

Параметр Retry имеет значение true или false, указывая, что сообщение следует повторить один раз, если возникла проблема.Если сообщение все еще не может быть отправлено, я хочу, чтобы возникла такая же исключительная ситуация, как и при вызове global: send (To, Message) вне блока try-catch.

Я знаю вышеработает, но меня беспокоит, является ли раздел false моего блока case хорошим erlang (например, используя erlang: Повышение () и rlang: get_stacktrace ()).

Любые мысли или предложения, чтобы сделать код "лучше"

Ответы [ 2 ]

9 голосов
/ 07 декабря 2010

Сделайте два разных вызова на global:send, один внутри try ... catch, другой нет:

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.

РЕДАКТИРОВАТЬ: Добавлен экспоненциальный откат.Будь как ... Нет, просто не могу этого сделать.

1 голос
/ 07 декабря 2010

Я бы сделал

erlang:error({badarg,{To,Message}})

вместо этого. Никакой реальной разницы, поскольку это также генерирует трассировку стека, но я думаю, что это более понятно erlang:raise/3 лучше для более общего использования, и если вы хотите что-то сделать с помощью трассировки стека.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...