Running line by line works but as a def I get right side will not match error

If I run the below line by line starting after the def hello do inside an iex shell it works but when I call the def directly from the iex shell ScAgent.hello I get the following error (see bottom).

I’m super new so this I’m sure is very easy for someone.


  def hello do
    socket_opts = [
      url: "ws://192.168.1.103:4000/socket/websocket",
      reconnect_interval: 10000
    ]
    {:ok, socket} = PhoenixClient.Socket.start_link(socket_opts)
    {:ok, _response, channel} = PhoenixClient.Channel.join(socket, "room:lobby")
    message = %{body: "Ok run some kind of command."}
    {:noreply, socket} = PhoenixClient.Channel.push_async(channel, "new_msg", message)
  end
end


iex: ScAgent.hello
** (MatchError) no match of right hand side value: {:error, :socket_not_connected}
    (scagent) lib/sc_agent.ex:22: ScAgent.hello/0
1 Like

I suspect that when you run {:ok, socket} = PhoenixClient.Socket.start_link(socket_opts) it returns immediately but only starts connecting in the background. When you run the next line too quickly, it won’t be connected yet. Typing it line by line in IEx is slow enough to allow for the socket to connect before the join command.

Unfortunately I’m not sure how to wait until PhoenixClient is connected (other than a loop with a timer that asks PhoenixClient.Socket.connected? periodically), but I only took a cursory glance at the code.

2 Likes

Easy way to do a dirty check on this concept is drop a process.sleep(10) or 50 between the two lines. In the long run this is not maintainable, so don’t use that as a solution but it will tell you if you have a race condition or not. Congratulations. This is the most difficult class of error to identify and debug.

1 Like

What is the best way to code this? Add a supervisor, agent ro genserver?

I’m trying to follow along but not sure if I understand what is shown at the bottom of this page.

I’d be looking for client to auto connect and auto heal and trying to reconnect over the life of the application running. If anyone has a more laid out example from beginning to end that would be sweet.

I was looking at the tests. Interesting piece of code – any pitfalls for doing it like this.


def wait_for_socket(socket) do
    unless Socket.connected?(socket) do
      wait_for_socket(socket)
    end
  end
1 Like

I’d throw in a Process.sleep(10) before the rewait, but I feel like there’s probably a better way to do this in general, yeah. Sorry, I haven’t really directly used Channels since I started phoenixing just as liveview came out (been using elixir for a while for infra-type things though).