Liveview and subscribing to a general topic vs iterating and subscribing individually

Just learning liveview so please excuse my limited knowledge

From reviewing the Demo CRUD example I want to subscribe to a topic via Phoenix.PubSub.subscribe to aid other views that need to update based on resources changing. While the demo has an example of that for the show view it does not have an example of how this is best addressed without reloading all the resources while on a page that has many resources IE the index view for example.

Currently I subscribe like so via my posts context.

def subscribe_post do
    Phoenix.PubSub.subscribe(MorphicPro.PubSub, @topic)
  end

  def subscribe_post(post_id) do
    Phoenix.PubSub.subscribe(MorphicPro.PubSub, @topic <> "#{post_id}")
  end

I’m trying to figure out the best use case approach to this problem.

Do I

A: Iterate over the list of posts and subscribe to them individually on the index page?
IE the subscribe_post/1. I assume this could have some negative side effects on performance if I loop over all resources on a given view and use this as the means to subscribe to them individually. This also seems like it’s the most effective in only reloading the given changed resource.

B: subscribe to a generic topic that will cause any subscribers to reload all their given resources for that topic more broadly. IE the subscribe_post/0
This seems like it will work with less effort but also can cause some unwanted side effects like reloading resources that have not changed. From what I understand this is how the example is currently doing this.

C: Should I batch topics via a more generic topic name IE the module name? Or a similar idea is that I create a topic for the given page of a resource so that anyone else reviewing that same page updates. I can see how this could be problematic for index views where a bunch of new resources are getting added randomly.

D: Following is an interesting idea, though I’m not sure how I would load the specific resources in question on this event. I will probably explore this idea regardless.

Maybe make a topic for just “changes” and push a message that has that resource type and ID
- Rockwell Schrock

An example of what I’d like to do is a basic like for a post and have the index update any number of visible post’s like count while viewing them on the index view.

  • How are you all currently doing this type of pattern?
  • Is there a name for this pattern?

I assume at the end of the day it’s really about how to be clever with your topics and how to best manage them.

After a little playing around I’ve learned that if I set a new assigns on the socket for posts where only one item in that list has changed the whole list of posts will re render as the diff includes all of the posts as the value as a whole has changed. This leads me to wonder if it’s worth trying to only isolate the data that has changed.

An example of what I mean is how I update the posts for the handle_info :updated on the index live view.

  def handle_info({Blog, [:post, :updated], post}, %{assigns: %{posts: posts}} = socket) do
    {:noreply,
     assign(
       socket, 
       posts: Enum.map(posts, fn p -> if p.id == post.id, do: post, else: p end)
       )}
  end


In this use case I only swap out the one post that came with the message vs doing a full lookup on the db.
As you can see here in my attached screen shot that the diff message shows that the posts as a whole as changed as I assume it re renders all the items in the view regardless if only one item in that posts assigns has changed. In this case I could say I do less IO because I’m not hitting the disk but instead trading the DB for CPU.

Is this worth it? I guess if the lists of posts was large this could be worse than just re hitting the db.