Erlang 处理状态超时时,从gen_状态正常退出

Erlang 处理状态超时时,从gen_状态正常退出,erlang,otp,Erlang,Otp,如何在gen_statem中优雅地退出状态超时?通常,对于genu statem,我可以从state函数返回“stop”或{stop,Reason},statem将终止。但是,如果使用从init返回的状态超时方法: {ok,StateName,State,{State_timeout,2000,timeout} handle_事件(state_timeout,timeout,StateName,state)方法在2000年后调用。从中返回“stop”将导致错误…: 守则: 处理事件(状态超时、超

如何在gen_statem中优雅地退出状态超时?通常,对于genu statem,我可以从state函数返回“stop”或{stop,Reason},statem将终止。但是,如果使用从init返回的状态超时方法:

{ok,StateName,State,{State_timeout,2000,timeout}

handle_事件(state_timeout,timeout,StateName,state)方法在2000年后调用。从中返回“stop”将导致错误…:

守则:

处理事件(状态超时、超时、状态名、状态)->
lager:警告(“设备的超时:~p处于状态:~p”, [State#State.uuid,StateName]),
{停止,超时}

错误:

14:29:56.992[警告]句柄事件(299):的超时 设备:未定义状态:init_auth 14:29:56.992[错误] 未定义(未定义):较大事件处理程序错误\u记录器\u较大事件\u退出 原因为{'EXIT',{{badmatch,[module,{state\u timeout,timeout

我可以从这个函数返回什么来优雅地退出?这可以通过状态\u timeout来完成吗?如果这是一个明显的问题,请给我指出正确的方向。这里的文档:似乎没有提到从状态\u timeout返回的任何内容。似乎我可以指定“下一个状态”,但退出似乎没有定义


感谢您的帮助!

系统生成错误,因为与停止消息相关联的原因不正常

在这个小示例中,状态机在达到20个超时条件后“正常”退出:

-module (statem).

-behaviour(gen_statem).

-export ([start_link/0]).
-export([init/1, callback_mode/0, terminate/3, code_change/4,handle_event/4]).

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

init([]) ->
    {ok, state1, #{info => 0, call => 0 , cast => 0, timeout => 0},[{timeout, 2000, timeout_event}]}.


callback_mode() ->
    handle_event_function.

handle_event(timeout,_EventContent,_State,#{timeout := 20}) ->
    io:format("max timeout count reached~n"),
    {stop, normal};
handle_event(EventType,EventContent,State,Data) ->
    io:format("EtventType : ~p~nEventContent : ~p~nState : ~p~nData : ~p~n", [EventType,EventContent,State,Data]),
    NewData = process_event(EventType,EventContent,State,Data),
    {next_state, State, NewData,[{timeout, 2000, timeout_event}]}.

terminate(_Reason, _State, _Data) ->
    ok.

code_change(_Vsn, State, Data, _Extra) ->
    {ok, State, Data}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

process_event(info,_EventContent,_State,Data) ->
    maps:update(info, maps:get(info, Data)+1, Data);
process_event(cast,_EventContent,_State,Data) ->
    maps:update(cast, maps:get(cast, Data)+1, Data);
process_event(timeout,_EventContent,_State,Data) ->
    maps:update(timeout, maps:get(timeout, Data)+1, Data);
process_event({call,From},EventContent,_State,Data) ->
    gen_statem:reply(From, {got,EventContent}),
    maps:update(call, maps:get(call, Data)+1, Data).
在建工程:

74> c(statem).                     
{ok,statem}
75> {ok,Pid} = statem:start_link().
{ok,<0.197.0>}
EtventType : timeout               
EventContent : timeout_event
State : state1
Data : #{call => 0,cast => 0,info => 0,timeout => 0}
EtventType : timeout              
EventContent : timeout_event
State : state1
Data : #{call => 0,cast => 0,info => 0,timeout => 1}
76> Pid ! hello.                  
EtventType : info
EventContent : hello
State : state1
Data : #{call => 0,cast => 0,info => 0,timeout => 2}
hello
EtventType : timeout               
EventContent : timeout_event
State : state1
Data : #{call => 0,cast => 0,info => 1,timeout => 2}
EtventType : timeout              
EventContent : timeout_event
State : state1
Data : #{call => 0,cast => 0,info => 1,timeout => 3}
77> gen_statem:cast(Pid,cast_msg).
EtventType : cast
EventContent : cast_msg
State : state1
Data : #{call => 0,cast => 0,info => 1,timeout => 4}
ok
...
80> gen_statem:call(Pid,call_msg).
EtventType : {call,{<0.190.0>,#Ref<0.571135265.1570766849.45359>}}
EventContent : call_msg
State : state1
Data : #{call => 0,cast => 3,info => 1,timeout => 17}
{got,call_msg}
EtventType : timeout
EventContent : timeout_event
State : state1
Data : #{call => 1,cast => 3,info => 1,timeout => 17}
...
EtventType : timeout              
EventContent : timeout_event
State : state1
Data : #{call => 2,cast => 4,info => 1,timeout => 19}
max timeout count reached
84> 

这是使用超时方法,而不是state\u timeout。您知道state\u timeout方法不起作用的原因吗?
-module (statem).

-behaviour(gen_statem).

-export ([start_link/0]).
-export([init/1, callback_mode/0, terminate/3, code_change/4,handle_event/4]).

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

init([]) ->
    {ok, state1, #{info => 0, call => 0 , cast => 0, timeout => 0},[{state_timeout, 2000, timeout}]}.


callback_mode() ->
    handle_event_function.

handle_event(state_timeout,_EventContent,_State,#{timeout := 20}) ->
    io:format("max timeout count reached~n"),
    {stop, normal};
handle_event(EventType,EventContent,State,Data) ->
    io:format("EtventType : ~p~nEventContent : ~p~nState : ~p~nData : ~p~n", [EventType,EventContent,State,Data]),
    NewData = process_event(EventType,EventContent,State,Data),
    {next_state, State, NewData,[{state_timeout, 2000, timeout}]}.

terminate(_Reason, _State, _Data) ->
    ok.

code_change(_Vsn, State, Data, _Extra) ->
    {ok, State, Data}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

process_event(info,_EventContent,_State,Data) ->
    maps:update(info, maps:get(info, Data)+1, Data);
process_event(cast,_EventContent,_State,Data) ->
    maps:update(cast, maps:get(cast, Data)+1, Data);
process_event(state_timeout,_EventContent,_State,Data) ->
    maps:update(timeout, maps:get(timeout, Data)+1, Data);
process_event({call,From},EventContent,_State,Data) ->
    gen_statem:reply(From, {got,EventContent}),
    maps:update(call, maps:get(call, Data)+1, Data).