bezzoon
bezzoon

Reputation: 2019

Phoenix PubSub event firing multiple times

  def join("world:lobby", _message, socket) do
    PubSub.subscribe(Rotb.PubSub, "zone_1")

    {:ok, socket}
  end


  def handle_info(%{message: message}, socket) do
    broadcast(socket, "shout", %{"socket_id" => socket.id, "message" => message})

    {:noreply, socket}
  end

  def handle_in("shout", payload, socket) do
    PubSub.broadcast(Rotb.PubSub, "zone_1", %{
      message: payload["message"]
    })

    {:noreply, socket}
  end

However the shout event happens multiple times on my client? It looks like it might appear an additional time for each other connection but not 100%.

Upvotes: 0

Views: 288

Answers (2)

Peaceful James
Peaceful James

Reputation: 2235

Please check to see if you are calling subscribe function in your mount function in the LiveView.

The mount function is called twice, and duplicate subscriptions will result in duplicate events being sent to handle_info.

Upvotes: 0

Danstan
Danstan

Reputation: 1771

If I understand correctly what you are doing, you want all connected clients to the phoenix channel to get the shout.

The PubSub subscription there makes sense.

The broadcast in handle info does not make sense because its for the current client. You should just be doing a push there. See your code below with screenshot of a React Native console with two clients connected.

defmodule MyAppWeb.TestChannel do
  use Phoenix.Channel

  alias Phoenix.PubSub

  def join("world:lobby", _message, socket) do
    PubSub.subscribe(MyApp.PubSub, "zone_1")

    {:ok, socket}
  end

  def handle_info(%{message: message}, socket) do
    IO.inspect({"NEW MESSAGE", message})
    push(socket, "shout", %{"socket_id" => socket.id, "message" => message})

    {:noreply, socket}
  end

  def handle_in("shout", payload, socket) do
    IO.inspect({"SHOUT", payload})

    PubSub.broadcast(MyApp.PubSub, "zone_1", %{
      message: payload["message"]
    })

    {:noreply, socket}
  end
end

enter image description here

The shout is sent from the android client. If you have two clients connected then you should see two different pids for each socket.

Now if you are just trying to broadcast the message to all connected clients, you should just use the broadcast/3 inside handle_in and don't use PubSub. PubSub is for pushing messages from outside the socket. Like some cron job that finds if some other external state has changed then pushes that to the clients. For broadcasting messages from one client to others then broadcast/3 inside handle_in is enough

Using broadcast inside handle_info with pubsub means all clients get the pubsub then they all broadcast. No what you want.

Upvotes: 1

Related Questions