Timeout when sending a channel message directly from one user to another

Hi all, hoping one of you experts might be able to point me to the error of my ways…

I’m attempting to allow a user to send a direct message to another user via a socket. I am finding every message times out, and I’m trying to find out why!

Here’s my code:

user_socket.ex assigns a UUID to the socket, and then identifies the socket using that UUID. I am expecting that it will then be possible to reference the socket topic by user:<uuid>.
(see https://hexdocs.pm/phoenix/Phoenix.Socket.html#c:id/1)

defmodule MyAppWeb.UserSocket do
  use Phoenix.Socket

  ## Channels

  # Room channel
  channel "room:*", MyAppWeb.RoomChannel

  @impl true
  def connect(_params, socket, _connect_info) do
    {:ok, assign(socket, :user_id, UUID.uuid4())}
  end

  @impl true
  def id(socket), do: "user:#{socket.assigns.user_id}"
end

In room_channel.ex I then provide a handler for the message topic which is the one I’ve chosen for users to be able to send one another direct messages:

defmodule MyAppWeb.RoomChannel do
  require Logger

  use Phoenix.Channel
  alias MyApp.RoomPresence

  def join("room:" <> _roomId, _message, socket) do
    # Send back the id that we have assigned to this particular user
    {:ok, %{ id: socket.assigns.user_id }, socket}
  end

  def handle_in("message", %{"to" => to, "body" => body}, socket) do
    socket.endpoint.broadcast("user:" <> to, "message", %{body: body, to: to})
    {:noreply, socket}
  end
end

When I attempt to send the message:

  1. It appears to have been successfully posted (no errors are visible)
  2. A few seconds later, a timeout is acknowledge on the client in the chan_reply_n topic, where n is a number representing the message sequence

My questions are:

  1. Am I doing something wrongly?
  2. How can I debug timeouts?

Thanks very much!!

Just make a user channel, like the room channel, and check on join that a user can only connect to it’s own.

It’s possible to multiplex many channels on a socket, and having a dedicated one per user is quite common.

2 Likes

Thanks that’s exactly what I have ended up doing. It would have been possible in this case to simplify the client-side code by not needing the additional channel. Is there any way of achieving that?