Phoenix conn is passed to wrong process in tests

I have a very basic phoenix 1.3-rc app (mix phx.new demo --no-ecto --no-brunch) - GitHub - chvanikoff/demo (3 commits: generate app, add dependency, add failing test suite) with 1 dependency - GitHub - chvanikoff/std_json_io: A simple library for Elixir that provides json over STDIO and in case I use conn = get conn, "/" stmt. more than 1 time:

conn = get conn, "/"
assert html_response(conn, 200) =~ "Response: {:ok"
conn = get conn, "/"
assert html_response(conn, 200) =~ "Response: {:ok"

I’m getting

{#Reference<0.0.5.203>, {200, [{“content-type”, “text/html; charset=utf-8”}, {“cache-control”, “max-age=0, private, must-revalidate”}, {“x-request-id”, “ldsn9mf6cjer1a601s7df3saasbfq9jr”}, {“x-frame-options”, “SAMEORIGIN”}, {“x-xss-protection”, “1; mode=block”}, {“x-content-type-options”, “nosniff”}], “<!DOCTYPE …”}}

sent to this receive stmt.: std_json_io/lib/std_json_io.ex at master · chvanikoff/std_json_io · GitHub

Can anyone explain me why this is happening?

Just tested against Phoenix 1.2.1 - same issue there

The error is not in phoenix… your library response was {:error, "timeout"}
since there is no structure related to phoenix in the library call:

 response = StdJsonIo.json_call(%{"key": "value"})

I recommend to track the expected behavior of your library for several scenarios.

I don’t really understand what you mean, since there’s no {:error, “timeout”}, I don’t pass any phx-related structures intentionally to anywhere in the lib and actually my question was not about the error.
The error happens in StdJsonIo, right. But it is very expected because the reason behind is that Phx structure of {#Ref, {200, [...]}} is somehow coming to the receive clause I was referring to. And what I really want to understand is not “how to fix this” but “why this structure ever gets there”.

wow, I was just writing I found this and here is your reply :slight_smile:
However doesn’t make much sense so far, so I’m still investigating…

Ok, I think I figured it out: the StdJsonIo function being called is in fact the same process as the controller where it is called from, and since that, message sent to controller gets to the receive block in the StdJsonIo.

Oh, that was my mistake, sorry. I thought the problem was with the test, so I cloned your demo repo and runned the tests. I didn’t explain that, so {:error, "timeout"} was the response for StdJsonIo.json_call that I got.

The original StdJsonIo repo recommends to create a module to handle the calls to the library and that module will be the Supervisor for the pool. I think that json_call was created to be runned inside the Supervisor. I would go in that direction to solve it.

I would add a rule o thumb, when you’re working with processes/messages using the default behaviors(GenServer, Monitor, Supervisor, etc) stick with the default behaviors and dont try to handle the messages yourself. In your case I would do a GenServer.call not a cast if you’re expecting an answer.

Np, but I wonder why you’ve got the timeout error because I made the example to be working as per my description, and timeout error means script returned nothing, like it was “python /path/to/script” instead of “python -u /path/to/script”… Anyway, thanks for the suggestion, but one of the biggest points of my fork was to get rid of that module creation requirement (which was for for something but definitely not this case). The fix was as simple as just filter expected messages in the mentioned receive clause, that’s why I was mostly interested in reason rather than solution.

A single static tag is unsafe. If you call json_call twice, and the first one takes longer than 10s, you might get the the response for the first call while you’re in the second call. Using make_ref would fix that.

You’re also not linking which means any failure will show up as a “timeout”.

All these things are handled for you when using GenServer.call / GenServer.reply.

I’ve added a few test cases and it seems you are right, thanks for pointing it out.