Confusion with PubSub and Channels

Aim : In a game, user 1 challenges user 2 to play. (say, chess)
user 1 can receive some updates via channel user:1 from server and some updates about user 2’s game during the game duration (5 min).

What have I tried so far?

  1. Tried to implement my own socket via Phoenix.Socket and channel (below).
  2. After I user 1 logs in → websocket connection is established on channel user:1
  3. Now he challenges user 2 (from a long list of users) and send the response on channel user:1 as "challenged",{challenged_to: 2} where challenged is message and rest payload. See handle_in/3 below

What’s the confusion?
When I do Accounts.subscribe(user_id) in handle_in/3 with the challenged_user_id , what happens?

  1. channel user:1 is subscribed to PubSub topic user:2 (is this right?)
  2. Any update by user:2 (when broadcasted to PubSub) will be automatically sent to user:1 with correct payload.
  3. If both of above don’t happen. Please explain.

In cursor_channel.ex

defmodule .... 
use MyAppWeb, :channel

.
.
.
  def handle_in("challenged", payload, socket) do
    %{challenged_to: challenged_to_user_id} = payload

    Accounts.subscribe(challenged_to_user_id)
    {:noreply, socket}
  end

In accounts.ex

def subscribe(user_id) do
    Phoenix.PubSub.subscribe(MyApp.PubSub, "user:#{user_id}")
  end

1 Like

If you use a channel per user I think you should not subscribe to the other users channels.

  • Player 1 subscribes to user:1
  • Player 2 subscribes to user:2
  • Player 1 sends a message to the channel user:1 with %{challenge: user_2_id}
  • in handle_in you publish a %{challenged_by: user_1_id} to channel user:2
  • Player 2 receives that message on its own user:2 channel.
1 Like

Does it make sense to use one channel per user?
Or should PubSub be better?

What are the pro/cons of both approaches?

I am trying to use PubSub - because when User 2 is not connected, and joins the game, i should be able to update user 1 that use 2 has joined.

How do I do that without PubSub?

You could create a game:42 topic for them to join so all messages related to that game are broadcast to all players.

1 Like

With this approach, I cannot restrict messages that must be sent to all (playing the game) except user 1.

Or is that possible when everyone joins a common topic game:42 ?

Sure. Naive approach would be to pattern match on the id of the sender and ignore of it’s your id.