Phoenix presence & presence_diff messages


I’m currently diving into world of websockets via Phoenix channels. Absolutely awesome stuff.

The thing I’m wondering is Phoenix presence. Almost all of the examples are chat-examples however my use-case is not a chat but rather a game.

Usually everybody handles the presence state diff-messages in Javascript. For example:

room.on("presence_diff", diff => {
  presences = Presence.syncDiff(presences, diff)

given this channel implementation:

defmodule PhoenixChat.RoomChannel do
  use PhoenixChat.Web, :channel
  alias PhoenixChat.Presence

  def join("room:lobby", _, socket) do
    send self(), :after_join
    {:ok, socket}

  def handle_info(:after_join, socket) do
    Presence.track(socket, socket.assigns.user, %{
      online_at: :os.system_time(:milli_seconds)
    push socket, "presence_state", Presence.list(socket)
    {:noreply, socket}

How can I suppress the sending of presence_diffs to clients? As I don’t want to expose the presence information to connected clients but keep it only on the server side.

1 Like

Two ways, you can also PubSub subscribe to a new process that does all the actual processing with the messages then posts to the client as needed, this would also let clients share a ‘processing’ actor. Or you can hook the ‘outgoing’ messages in Phoenix Channels (detailed in the docs) for the outgoing message of “presence_diff” then do what you wish, such as pushing it out or canceling it or whatever. :slight_smile:

For note, if the client should get the pubsub messages then they should get them all or will desync.

If the client should get none then it should be handled by another process.

The client should never just get ‘some’, what you probably want here is an intermediary process as well to coalesce the updates.

1 Like

Intercepting would be something like this?

intercept ["presence_diff"]

def handle_out("presence_diff", msg, socket) do
    {:noreply, socket}

The target is to use the channel for sending in-game data and event to clients and utilize the presence internally on the server-side. Client side would only connect the websocket (swift / iOS, Android) and get updates on the game events.
Clients wouldn’t get updates on who is online and who is not (prevent players for example attacking players who go offline in the hopes of catching them off-guard)

That is precisely it. :slight_smile:

Personally I would have a few processing processes that handle the messages of what is happening, and ‘they’ would then send messages to topics to send updates to clients, and the clients would connect to as many topics as they need for the data they want to receive. :slight_smile:

1 Like

Great. This helps me forward. Thanks!

By the way. Gotta love the Elixir/Phoenix community. You guys rock!

1 Like

intercepting is the way to go to easily filter out the presence_diff events

1 Like