LiveView + PubSub topics with GenServer to keep state for each

hey all! I’ve followed an example online on how to create a simple “counter” program with LiveView where changes are reflected for all clients. (GitHub - dwyl/phoenix-liveview-counter-tutorial: 🤯 beginners tutorial building a real time counter in Phoenix 1.6.2 + LiveView 0.16.4 ⚡️)

The LiveView mounts, renders, and handle_events and the state is moved out of LV and into GenServer. A utility function inside the GenServer broadcasts the last count to the PubSub topic.

I now want to create multiple counters where each has it’s own count.
If (in theory) i could generate a slug that represents the topic for each each counter and broadcast/subscribe to that topic, how can this be done being that the topic is being set by a topic() fn inside the GenServer.

I think my question is probably due to a misunderstanding of GenServers and LV but it seems that a single GenServer would not be able to keep state for all the counters? Does the name of each GenServer need to be unique as well? How can we set the name first of all (if this is even necessary) and then also “dynamically” subscribe to each topic.

Im thinking a GenServer must be started with start_link inside the LV and the custom counter-id can be passed in but not sure if this would be right/necessary.

thank you!!!

1 Like

Are you beginning with a predetermined number of counters, or are you wishing for new counters to be created and destroyed dynamically by user action?

Either way, you would most likely want a separate GenServer for each topic to isolate the state of each counter, and you would want to start your count servers under a supervision tree, rather than calling start_link directly from any LiveView.

1 Like

Goal is for new counters to be added. With that being the case, is it possible in an elixir project to add GenServers to the supervision tree as they are created even if they are not defined in application.ex when the project is started up?

i think i’ll potentially end up doing something with Registry and DynamicSupervisor but if u have any other suggestions pls let me know :slight_smile:

Yes, exactly! You are onto the solution I would suggest. You can dynamically start your GenServers as needed under a DynamicSupervisor that is started in the top level supervision tree of your Application. You do not want to dynamically name arbitrary numbers of processes with atoms since atoms are never garbage collected, so also start a supervised Registry and name your GenServers with the :via option, probably using the pubsub topic name as your naming term e.g. {:via, Registry, {LiveViewCounter.Registry, topic}}.

I am relatively new to Elixir/Phoenix/LiveView, having only built a few small projects, but I had free time and thought this would be an interesting problem to tackle for the sake of my own learning experience with LiveView. This repo has a working implementation if you want to clone it and try it out : )

If anyone with more experience reads this and has feedback or criticism on my approach, I would welcome it!

3 Likes

so awesome @msimonborg !!! haven’t ran it but will as soon as i get a chance thank you !!

wow you’re fast! i’ve ran it and that did the trick, thanks a million it’s blows my mind how simple it is to do these kinds of things with elixir!

1 Like

My pleasure! If you have any questions about anything in there, let me know. Elixir really is a joy to use when you start getting familiar with the language features and OTP. Cheers!

1 Like