2

Erlang 新手,只是在理解新范式时遇到了一些麻烦!

好的,所以我在 OTP gen_server 中有这个内部函数:

my_func() ->
Result = ibrowse:send_req(?ROOTPAGE,[{"User-Agent",?USERAGENT}],get),
case Result of
    {ok, "200", _, Xml} -> %<<do some stuff that won't interest you>>
,ok;
{error,{conn_failed,{error,nxdomain}}} -> <<what the heck do I do here?>>
end.

如果我忽略了处理连接失败的情况,那么我会收到一个传播到主管的退出信号,它会与服务器一起关闭。

我想要发生的事情(至少我认为这是我想要发生的事情)是在连接失败时我想暂停然后重试 send_req 说 10 次,此时主管可能会失败。

如果我做这种丑陋的事情......

{error,{conn_failed,{error,nxdomain}}} -> stop()

它会关闭服务器进程,是的,我可以使用我的(在 10 秒内尝试 10 次)重启策略,直到它失败,这也是预期的结果,但是当我从服务器到主管的返回值是“好的”时真的很想返回 {error,error_but_please_dont_fall_over_mr_supervisor}。

在这种情况下,我强烈怀疑我应该处理所有业务问题,例如在“my_func”中重试失败的连接,而不是试图让进程停止,然后让主管重新启动它以便再次尝试。

问题:在这种情况下,“Erlang 方式”是什么?

4

1 回答 1

2

我也是erlang的新手..但是这样的事情怎么样?

代码很长只是因为注释。我的解决方案(我希望我已经正确理解了您的问题)将接收最大尝试次数,然后进行尾递归调用,这将通过将最大尝试次数与下一次进行模式匹配来停止。使用 timer:sleep() 暂停以简化事情。

%% @doc Instead of having my_func/0, you have
%% my_func/1, so we can "inject" the max number of
%% attempts. This one will call your tail-recursive
%% one
my_func(MaxAttempts) ->
    my_func(MaxAttempts, 0).

%% @doc This one will match when the maximum number
%% of attempts have been reached, terminates the
%% tail recursion.
my_func(MaxAttempts, MaxAttempts) ->
    {error, too_many_retries};

%% @doc Here's where we do the work, by having
%% an accumulator that is incremented with each
%% failed attempt.
my_func(MaxAttempts, Counter) ->
    io:format("Attempt #~B~n", [Counter]),
    % Simulating the error here.
    Result = {error,{conn_failed,{error,nxdomain}}},
    case Result of
        {ok, "200", _, Xml} -> ok;
        {error,{conn_failed,{error,nxdomain}}} ->
            % Wait, then tail-recursive call.
            timer:sleep(1000),
            my_func(MaxAttempts, Counter + 1)
    end.

编辑:如果此代码处于受监督的进程中,我认为最好有一个 simple_one_for_one,您可以在其中动态添加所需的任何工作人员,这是为了避免由于超时而延迟初始化(在 one_for_one 中,工作人员开始顺序,并且此时进入睡眠状态将阻止其他进程初始化)。

EDIT2:添加了一个示例 shell 执行:

1> c(my_func).
my_func.erl:26: Warning: variable 'Xml' is unused
{ok,my_func}
2> my_func:my_func(5).
Attempt #0
Attempt #1
Attempt #2
Attempt #3
Attempt #4
{error,too_many_retries}

每条打印消息之间有 1 秒的延迟。

于 2012-06-20T01:24:52.063 回答