R – Two quick consecutive calls to wf:insert_bottom end up in the reverse order

erlangnitrogen

Using Nitrogen, the Erlang web framework, I have the following method that receives messages and adds them to the bottom of an html element:

receive_messages() ->
  receive
    Message ->
      io:format("~p received ~p", [self(), Message]),
      wf:insert_bottom(messages, [#p{}, #span { text=io_lib:format("~p", [Message]) }])
  end,
  wf:comet_flush(),
  receive_messages().

It is set as the usual way for comet:

wf:comet(fun() -> receive_messages() end)

It receives two messages very quickly:

<0.907.0> received {starting_chat,<0.905.0>}
<0.907.0> received {connected_to,<0.902.0>}

This is what I see in the HTML:

{connected_to, <0.902.0>}
{starting_chat, <0.905.0>}

Somehow, they ended in the reverse order.

I've started adding timer:sleep() calls to this method. With 50 milliseconds, they are in the correct order, with 20 they are not. When they are in the incorrect order they seem to be always in the incorrect order, it seems very deterministic.

Any ideas why? Is this a bug? Any ideas what should I do to get them in the correct order other than sleeping?

Also asked on the mailing list, in case there's more info there.

Best Answer

wf_comet.erl has a "strange" reverse call after applying inner_collect_content. My guess is that inner_collect_content used to be tail-recursive sometime ago.

If you apply the timeout, your messages are collected in different loops, one-by-one, so the order is not reversed anymore.


There seems to be a commit fixing this on another repository:

http://github.com/gersh/nitrogen/commit/a8bfcb23d003e68f7394a0455285beeb0fbf9b09

Related Topic