slouchpie

slouchpie

Associations, PubSub and live-updating - larger payload or enumerable iteration?

Imagine this familiar situation. We have a LiveView that renders a list of posts. Each post has an author (user) and multiple comments. Each comment also has an author (user). The LiveView process subscribes to some “new comment” topic. When a new comment is created on a post, this information is broadcast.

In this situation, it is clear that the PubSub payload should include the comment’s author preloaded. This could be a new user, who registered after the LiveView mounted. All is good.

Now imagine a different situation. We have a LiveView that renders a restaurant menu. A user can add items to their basket. A basket can be shared, so multiple users are using the same basket. The LiveView process subscribes to some “new basket item” topic. When an item is added to the basket, this information is broadcast. The LiveView is also subscribed to menu changes, e.g. menu item price changes. This means the LiveView process “knows” all the menu details.

In this situation, the basket item is associated to a menu item. My scruple is this: should the PubSub payload include the menu item preloaded on the created basket item struct? It seems wasteful, since, assuming our LiveView also subscribes to menu updates, the LiveView already “knows” the menu item details (not using streams here). Moreover, if, say, a menu item price changes, we will need update all assigned basket items that have this menu item preloaded.

With this in mind, it seems silly to trust/use a basket item’s preloaded menu item association. So I naturally think “OK, I will just find the menu item in the menu assign and infer details from that for rendering the basket item”. However, my menu items are a list, and iterating over a list for every basket item render is obviously very bad. OK, so maybe I should instead have a map of menu item IDs to menu items? Now the code feels very unwieldy, since I am perpetually transforming lists into maps, just for easy access of assoc details.

This entire train of thought has been a thorn in my side while doing LiveView development. I feel like no matter which approach I take, I am begetting obvious inefficiency.

Does anyone else feel this way? Does anyone have ancient secrets of efficient nested association assigns they want to share?

P.S. I love LiveView. It is awesome. I use it every day.

Most Liked

cmo

cmo

Obvious because you’ve measured it?

cmo

cmo

I merely intended to trigger the thought in you that maybe you should benchmark things instead of thinking you know what is and is not inefficient. I am sometimes surprised that my intuition about what will be faster is wrong when I benchmark different approaches.

Especially when you’re talking about a restaurant menu, which is not a large data structure.

slouchpie

slouchpie

Here is a pseudo-example

defmodule MyApp.Blurb do
  @moduledoc """
  BLURB = Brute Live Update of Rendered Basket
  """
  alias MyApp.Baskets.NebulexCache
  alias MyApp.Baskets.Basket

  @topic "blurb"
  def topic(basket_id), do: @topic <> basket_id
  def subscribe(basket_id), do: Phoenix.PubSub.subscribe(MyApp.PubSub, topic(basket_id))

  def broadcast(basket_id),
    do: Phoenix.PubSub.broadcast(MyApp.PubSub, topic(basket_id), {:blurb, basket_id})

  @doc """
  A simple way of updating a displayed basket in real-time.

  When a basket is updated in any kind of way, we broadcast just
  the basket ID and a message like `basket_updated`.

  Subscribers should then fetch the basket but ensure to do so using
  Nebucache or whatever we are using to cache function results.


  1. clear nebucache for a basket
  2. broadcast the basket ID and message
  """
  @spec clear_and_broadcast(Basket.id()) :: :ok
  def clear_and_broadcast(basket_id) do
    NebulexCache.clear_basket_id(basket_id)
    broadcast(basket_id)
  end
end

Then, if my basket changes in any kind of way at all (or even if something nested within basket, e.g. if someone changes the quantity of one of the items) then I just write a single line in the context function:

Blurb.clear_and_broadcast(basket_id)

I would love any feedback or criticism. I’m sure there are pitfalls with this approach that I am not seeing (such is life).

Where Next?

Popular in Discussions Top

Donovan
Hello everyone, I’m so glad to have discovered this awesome community. Thanks for creating it! This is my second post, and apologies for...
New
blackode
Elixir Upgrading is so Simple in Ubuntu and It worked for me Ubuntu 16.04 git clone https://github.com/elixir-lang/elixir.git cd elixir...
New
Crowdhailer
I’ve been hearing much about the new formatter and it’s something I have been keen to try. I find examples buy far the most illuminating...
248 19365 150
New
WildYorkies
It seems that the more I read, the more I find Elixir users speaking about all the ways that Elixir is not good for x, y, and z use cases...
New
Markusxmr
Since Drab has been developed for a while in the open, introducing the Liveview functionality in a way it happend appears to undermine th...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
axelson
Decided against including more info in the title, but the gist is that Plataformatec sponsored projects will continue with the assets bei...
New
nunobernardes99
Hi there Elixir friends :vulcan_salute: In a recent task I was on, I needed to check in two dates which of them is the maximum and which...
New
mmmrrr
Just saw that dhh announced https://hotwire.dev/ Is it just me or is this essentially live view? :smiley: Although I like the “iFrame-e...
New
AstonJ
It’s been a while since we’ve had a thread like this, so what better way to kick off the year with :003: What does being an Elixir user ...
New

Other popular topics Top

minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29703 241
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New

We're in Beta

About us Mission Statement