<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Thanks - In the back of my head I thought it was the case, but couldn't find that sentence. Log proved useful to find the cause.<div class=""><br class=""></div><div class="">Regards,</div><div class="">Peter.<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On 31 Jul 2019, at 10:16, Jesper Louis Andersen <<a href="mailto:jesper.louis.andersen@gmail.com" class="">jesper.louis.andersen@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">It is documented behaviour for next_event:</div><br class="">This action does not set any transition_option() but instead stores the specified EventType and EventContent for insertion after all actions have been executed.  <div class=""><br class=""></div><div class=""><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">My guess is that replies are sent as early as possible because this exposes concurrency to the maximum.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br class=""></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">I would also be very cautious around relying on orderings like these in a system since that is where concurrency bugs are hidden.</div><br class=""></div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jul 31, 2019 at 10:41 AM Peter Morgan <<a href="mailto:peter.james.morgan@gmail.com" class="">peter.james.morgan@gmail.com</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;" class="">Hi,<div class=""><br class=""></div><div class="">I regularly use the following pattern in gen_statem:</div><div class=""><br class=""></div><div class=""><div class="">handle_event({call, From}, a, _, _) -></div><div class="">  {keep_state_and_data, [{next_event, internal, work}, {reply, From, ok}]};</div></div><div class=""><br class=""></div><div class="">Where `work` is some side effect that needs to be done, and may be used by several other actions (hence wrapping it in a next_event) but the result is unimportant and doesn’t affect the reply. I use  next_event rather than calling work() directly because it can be traced via sys.</div><div class=""><br class=""></div><div class="">My assumption was that work would be processed before the reply was sent to the caller - i.e., that the actions were processed in order.</div><div class=""><br class=""></div><div class="">Instead, it appears that the reply action is processed immediately?</div><div class=""><br class=""></div><div class="">To work around this I have started using:</div><div class=""><br class=""></div><div class=""><div class="">handle_event({call, From}, a, _, _) -></div><div class="">  {keep_state_and_data, [{next_event, internal, work}, {next_event, internal, {reply, From, ok}]}};</div></div><div class=""><div class="">handle_event(internal, {reply, From, Result}, _, _) -></div><div class="">    {keep_state_and_data, {reply, From, Result}}.</div></div><div class=""><br class=""></div><div class="">The above ensures that work is completed before the reply is sent (result of the work is a side-effect here) - but is a rather ugly solution.</div><div class=""><br class=""></div><div class="">Is the above intended behaviour? In some cases the `work` event causes state changes, or queueing subsequent other work (via next_event, internal) that was expected to be completed before the {reply, From, ok} was consumed.</div><div class=""><br class=""></div><div class="">The above ordering of actions assumption caught me out recently, the early reply was causing a process to be killed before it had actually completed its work causing an unclean shutdown in a system.</div><div class=""><br class=""></div><div class="">BTW the additional of log is very useful in failure analysis - what did this statem recently do? :) thanks!</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Peter.</div><div class=""><br class=""></div><div class="">Full example:</div><div class=""><br class=""></div><div class=""><div class="">-module(exaple_statem_reply).</div><div class=""><br class=""></div><div class="">-behaviour(gen_statem).</div><div class="">-export([a/0]).</div><div class="">-export([b/0]).</div><div class="">-export([callback_mode/0]).</div><div class="">-export([handle_event/4]).</div><div class="">-export([init/1]).</div><div class="">-export([start/0]).</div><div class="">-export([stop/1]).</div><div class="">-include_lib("kernel/include/logger.hrl").</div><div class=""><br class=""></div><div class="">start() -></div><div class="">    gen_statem:start({local, ?MODULE},</div><div class="">                     ?MODULE,</div><div class="">                    [],</div><div class="">                    [{debug, [log, trace]}]).</div><div class=""><br class=""></div><div class="">a() -></div><div class="">    gen_statem:call(?MODULE, ?FUNCTION_NAME).</div><div class=""><br class=""></div><div class="">b() -></div><div class="">    gen_statem:call(?MODULE, ?FUNCTION_NAME).</div><div class=""><br class=""></div><div class="">stop(S) -></div><div class="">    gen_statem:stop(S).</div><div class=""><br class=""></div><div class="">init([]) -></div><div class="">    {ok, limbo, #{}}.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">callback_mode() -></div><div class="">    handle_event_function.</div><div class=""><br class=""></div><div class="">handle_event({call, From}, a, _, _) -></div><div class="">    {keep_state_and_data, [nei(work), {reply, From, ok}]};</div><div class=""><br class=""></div><div class="">handle_event({call, From}, b, _, _) -></div><div class="">    {keep_state_and_data, [nei(work), nei({reply, From, ok})]};</div><div class=""><br class=""></div><div class="">handle_event(internal, work, _, _) -></div><div class="">    keep_state_and_data;</div><div class=""><br class=""></div><div class="">handle_event(internal, {reply, From, Result}, _, _) -></div><div class="">    {keep_state_and_data, {reply, From, Result}}.</div><div class=""><br class=""></div><div class="">nei(Event) -></div><div class="">    {next_event, internal, Event}.</div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">1>   exaple_statem_reply:start().</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">*DBG* exaple_statem_reply enter in state limbo</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">*DBG* exaple_statem_reply consume internal init_state in state limbo</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">{ok,<0.161.0>}</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">2>   exaple_statem_reply:a().</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">*DBG* exaple_statem_reply receive call a from <0.78.0> in state limbo</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">*DBG* exaple_statem_reply receive internal work in state limbo</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">*DBG* exaple_statem_reply send ok to <0.78.0></span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">*DBG* exaple_statem_reply consume call a from <0.78.0> in state limbo</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">ok</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">*DBG* exaple_statem_reply consume internal work in state limbo</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">3>   sys:get_status(exaple_statem_reply).</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">{status,<0.161.0>,</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">        {module,gen_statem},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">        [[{'$ancestors',[<0.78.0>]},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">          {'$initial_call',{exaple_statem_reply,init,1}}],</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">         running,<0.161.0>,</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">         [{trace,true},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">          {log,[3,</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                {{consume,{internal,work},limbo,limbo},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                 exaple_statem_reply,#Fun<gen_statem.1.50707408>},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                {{consume,{{call,{<0.78.0>,</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                                  #Ref<0.2400559651.2919759873.28633>}},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                           a},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                          limbo,limbo},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                 exaple_statem_reply,#Fun<gen_statem.1.50707408>},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                {{out,ok,{<0.78.0>,#Ref<0.2400559651.2919759873.28633>}},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                 exaple_statem_reply,#Fun<gen_statem.1.50707408>},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                {{in,{internal,work},limbo},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                 exaple_statem_reply,#Fun<gen_statem.1.50707408>},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                {{in,{{call,{<0.78.0>,#Ref<0.2400559651.2919759873.28633>}},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                      a},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                     limbo},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                 exaple_statem_reply,#Fun<gen_statem.1.50707408>},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                {{consume,{internal,init_state},limbo,limbo},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                 exaple_statem_reply,#Fun<gen_statem.1.50707408>},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                {{enter,limbo},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                 exaple_statem_reply,#Fun<gen_statem.1.50707408>}]}],</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">         [{header,"Status for state machine exaple_statem_reply"},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">          {data,[{"Status",running},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                 {"Parent",<0.161.0>},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                 {"Logged Events",</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                  [{enter,limbo},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                   {consume,{internal,init_state},limbo,limbo},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                   {in,{{call,{<0.78.0>,#Ref<0.2400559651.2919759873.28633>}},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                        a},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                       limbo},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                   {in,{internal,work},limbo},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                   {out,ok,{<0.78.0>,#Ref<0.2400559651.2919759873.28633>}},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                   {consume,{{call,{...}},a},limbo,limbo},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                   {consume,{internal,work},limbo,limbo}]},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">                 {"Postponed",[]}]},</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">          {data,[{"State",{limbo,#{}}}]}]]}</span></div><div style="margin:0px;font-stretch:normal;font-size:14px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">4> </span></div></div><div class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><br class=""></span></div><div class=""><br class=""></div></div>_______________________________________________<br class="">
erlang-questions mailing list<br class="">
<a href="mailto:erlang-questions@erlang.org" target="_blank" class="">erlang-questions@erlang.org</a><br class="">
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank" class="">http://erlang.org/mailman/listinfo/erlang-questions</a><br class="">
</blockquote></div><br clear="all" class=""><div class=""><br class=""></div>-- <br class=""><div dir="ltr" class="gmail_signature">J.</div>
</div></blockquote></div><br class=""></div></body></html>