我怎么知道它是erlang中主管重新启动的最后一个循环周期

时间:2016-02-25 11:42:21

标签: erlang otp supervisor gen-fsm

我有一名simple_one_for_one主管,其中有gen_fsm个孩子。 我希望每个gen_fsm子节点仅在最后一次终止时发送消息。 有没有办法知道最后一个周期是什么时候?

这是我的主管:

-module(data_sup).

-behaviour(supervisor).

%% API
-export([start_link/0,create_bot/3]).

%% Supervisor callbacks
-export([init/1]).

%%-compile(export_all).


%%%===================================================================
%%% API functions
%%%===================================================================

start_link() ->
  supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
 RestartStrategy = {simple_one_for_one, 0, 1},
 ChildSpec = {cs_fsm, {cs_fsm, start_link, []},
 permanent, 2000, worker, [cs_fsm]},
 Children = [ChildSpec],
 {ok, {RestartStrategy, Children}}.

create_bot(BotId, CNPJ,Pid) ->
  supervisor:start_child(?MODULE, [BotId, CNPJ, Pid]).

Pid是进程的Pid,它启动了主管并发出启动孩子的命令。

-module(cs_fsm).

-behaviour(gen_fsm).
-compile(export_all).

-define(SERVER, ?MODULE).
-define(TIMEOUT, 5000).

-record(params, {botId, cnpj, executionId, pid}).

%%%===================================================================
%%% API
%%%===================================================================

start_link(BotId, CNPJ, Pid) ->
  io:format("start_link...~n"),
  Params = #params{botId = BotId, cnpj = CNPJ, pid = Pid},
  gen_fsm:start_link(?MODULE, Params, []).


%%%===================================================================
%%% gen_fsm callbacks
%%%===================================================================

init(Params) ->
  io:format("initializing~n"),
  process_flag(trap_exit, true),
  {ok, requesting_execution, Params, 0}.

requesting_execution(timeout,Params) ->
  io:format("erqusting execution"),
  {next_state, finished, Params,?TIMEOUT}.

finished(timeout, Params) ->
  io:format("finished :)~n"),
  {stop, normal, Params}.

terminate(shutdown, _StateName, Params) ->
  Params#params.pid ! {terminated, self(),Params},
  ok;

terminate(_Reason, _StateName, Params) ->
  ok.

我的观点是,如果进程在任何状态中失败,它应该仅在主管最后一次重启时发送消息(根据其重启策略)。

如果gen_fsm失败,是否从具有相同状态数据的相同状态重新启动?如果不是我怎么能导致它发生?

1 个答案:

答案 0 :(得分:3)

您可以添加将消息发送到Module:terminate/3函数,当StateName函数之一返回{stop,Reason,NewStateData}时,调用该函数以指示gen_fsm应该停止。< / p>

gen_fsm是一个有限状态机,因此您可以决定它在状态之间的转换方式。触发最后一个循环的东西也可以在传递给StateData的{​​{1}}中设置一些内容,以便处理状态的函数知道它是最后一个循环。除非您提供一些我们可以分析和评论的代码,否则很难给出更具体的答案。

进一步澄清后编辑:

主管不会通知其子女他们重新启动他们的时间,也无法通知孩子这是最后一次重启。后来这只是因为它不知道它将是最后一次,直到主管进程再次崩溃,主管无法预测。只有在孩子崩溃后,主管才能计算出孩子在一段时间内坠毁的次数,以及是否允许再次重新启动孩子,或者是否是最后一次重启,现在是时候主管也要死了。 / p>

然而,没有什么能阻止孩子注册,例如在ETS表中,重新启动了多少次。但它当然无助于扣除哪个重启是最后一个。

编辑2:

当主管重新启动子节点时,它使用标准Module:StateName/3函数从头开始。儿童崩溃前的任何先前状态都将丢失。

请注意,崩溃是一种特殊情况,并不总是可以恢复状态,因为崩溃可能已经破坏了状态。而不是试图恢复状态或在重新启动孩子时询问主管,为什么不首先防止崩溃?您有两种选择:

我。使用try/catch来捕捉任何异常情况并采取相应措施。可以捕获任何可能导致进程崩溃并导致管理员重新启动它的错误。您可以将init添加到try/catch进程内的任何条目函数中,以便在崩溃服务器之前捕获任何错误条件。请参阅example function 1example function 2

gen_fsm

II。在进程终止时生成一个新进程来处理作业并捕获read() -> try try_home() orelse try_path(?MAIN_CFG) orelse begin io:format("Some Error", []) end catch throw:Term -> {error, Term} end. try_read(Path) -> try file:consult(Path) catch error:Error -> {error, Error} end. 信号。这允许EXIT异步处理作业并以自定义方式处理任何错误(不一定通过重新启动过程作为主管会这样做)。标题为Error Handling的此部分介绍了如何捕获来自子进程的gen_fsm信号。这是exit中的example of trapping signals。检查包含一些子句的gen_server函数,以捕获来自子进程的不同类型的handle_info消息。

EXIT