1

My use case is to have multiple users connected to a lobby/waiting room, but only two of them will be picked from the lobby to start a conversation, after which they should be removed from the lobby. How can I implement that? Note that in this system the users aren't registered and don't have usernames. They should directly come in from the webpage.

Apparently the track and untrack functions also have variants that accept pid as an argument. However I'm not sure how I can retrieve the pids of the processes in the first place, when the conversation needs to be started.

Is the function self() the correct one to use in this case? i.e. maybe I can write

def handle_info(:after_lobby_join, socket) do
  Presence.track(socket, "lobby", %{
    pid: self()
  })

  {:noreply, socket}
end

def handle_info(:start, socket) do
  pid1 = hd(Presence.list(socket)["lobby"][:metas])[:pid]
  # Start the conversation by sending messages individually to pid1 and pid2
  ...
  untrack(pid1, "my_app:lobby", "lobby")
  {:ok, socket}
end

Or am I overcomplicating the issue/not understanding Presence correctly?

There's also a phx_ref field but I don't seem to be able to use it for this purpose.

Also, apparently I would only want to send "start_conversation" messages to the two users being picked but not the others in the lobby. I see that the function push sends messages to a designated socket. But if I am keeping track of the pid, can the corresponding sockets be identified from the pid?

xji
  • 7,341
  • 4
  • 40
  • 61

1 Answers1

0

I solved my initial question using individual user channels eventually. I just let the frontend generate random user IDs.

A solution without using user channels is proposed in Elixir forum. It doesn't use Presence though.

def handle_info({:new_user, socket}, [{us1, ref1}, {us2, ref2}]) do
  # we had 2 users, a new one joined, so that's 3
  user_sockets = [socket, us1, us2]
  # we can create a room for them now
  create_new_room(user_sockets)
  # and clean the state
  Enum.each([ref1, ref2], fn ref ->
    Process.demonitor(ref)
  end)
  {:noreply, []}
end

def handle_info({:new_user, socket}, waiting_user_sockets) do
  # otherwise just add the new users to the waiting users list
  ref = Process.monitor(socket)
  {:noreply, [{socket, ref} | waiting_user_sockets]}
end

def handle_info({:DOWN, ref, :process, _object, _reason}, waiting_user_sockets) do
  # remove the disconnected socket
end
xji
  • 7,341
  • 4
  • 40
  • 61