real-time updated using same handle_info but on another live-view

Hello there, long time no see :slight_smile:
I started to play around with a old project (phoenix 1.6, not the new one .7), a little question I have considering live view and real-time updates. I have a non-working (:D) chat app. When a message is created:

def subscribe do
    Phoenix.PubSub.subscribe(Friendczar.PubSub, "messages")
end

 def create_message(attrs \\ %{}) do
    %Message{}
    |> Message.changeset(attrs)
    |> Repo.insert()
    |> broadcast(:message_created)
end
def broadcast({:ok, message}, event) do    

  Phoenix.PubSub.broadcast(
    Friendczar.PubSub,
    "messages",
    {event, message}
  )
  {:ok, message}
end

then, in live view on /messages:

def mount (...) if connected?(socket), do: Messages.subscribe() (...) end
def handle_event("send_message", %{"message" => attrs}, socket) do
    case Messages.create_message(attrs) do
      {:ok, message} ->
        changeset_for_message = Messages.change_message(%Message{})
        socket = assign(socket, changeset_for_message: changeset_for_message)
        {:noreply, socket}
      {:error, %Ecto.Changeset{} = changeset_for_message} ->
        socket = assign(socket, changeset_for_message: changeset_for_message)
        {:noreply, socket}
      end
  end

  def handle_info({:message_created, message}, socket) do
    messages = socket.assigns[:messages] || []
      socket =
        update(
          socket,
          :messages,
          fn messages -> messages ++ [message] end
        )

      {:noreply, socket}
    end

and that works pretty well. I mean that on creation of a message, it live broad casts itself on all subscribed to the Pub “users”.
However, in a another live view, lets say /test I do subscribe again to the “topic” in mount, then I do have the same handle_info function, but when a message is created it does not live-updates in /test. Only in /messages. What am I missing? I think the logic is right.

Best Regards

You’re certainly not doing anything intrinsically wrong here. It should work like you explained, given that you have the same mount and handle_info you that second LV.
You probably have some kind of small bug somewhere, but it’s hard to help without that seconde LV code, under the /test path.

1 Like

Will post the full LV for /test path without the def render.

def mount(params, session, socket) do
    if connected?(socket), do: Messages.subscribe()
    (...)
    messages_by_current_user = Messages.list_messages_by_current_user(current_user)   
    socket = assign(
        socket,
        (...)
        messages_by_current_user: messages_by_current_user
      )
    {:ok, socket}
  end

   def handle_info({:message_created, message}, socket) do   
      socket =
        update(
          socket,
          :messages_by_current_user,          
          fn messages_by_current_user -> messages_by_current_user ++ [message] end
        )

      {:noreply, socket}
    end

The only think that is not the same is the variable name that I pass to the heex, but what could not be a problem. Started looking for bugs, will post if anything appears. Thanks!

Is there a mistake in your code copy-paste (or maybe I’m just blind to it)? I don’t see that your handle_event callback ever calls Message.broadcast/2. If it’s not broadcasting the message result, that would explain why another subscriber isn’t getting messages.

It looks handle_event("send_message", ...) calls Messages.create_message(...) which then calls Messages.broadcast(...).

Maybe the bug is in the HEEx template and how the @messages_by_current_user assign is used?

Ah, so it’s on the “I’m just blind to it” side ;-p.

1 Like