nidu

nidu

What's the idiomatic way to broadcast messages related to context updates

Hello, I have a code organization question.

Let’s say I have a Blog app with posts.ex context which is responsible for managing posts. When a new post is added - I’d like to send a pubsub message about it using BlogWeb.Endpoint.broadcast.

What would be the right way to do it? The simplest one to me is to broadcast inside Blog.create_post, but it feels that Blog shouldn’t depend on BlogWeb. Other options I see are:

  1. Add another posts.ex context inside BlogWeb, that will either wrap methods like create_post (or for clarity create_post_and_broadcast and add broadcast there. This feels not to so bad, but caller has to know that for some operations he has to go to BlogWeb.Posts instead of Blog.Posts.
  2. Or again create this new posts.ex and just provide broadcast methods there, then caller must call broadcast after create_post, which sounds error prone.

Could you please tell if there’s a clear idiomatic way of doing it or share a good example? Thanks!

Marked As Solved

drl123

drl123

What version of Phoenix are you running? Phoenix 1.6 starts the pubsub server under the app (Blog, not BlogWeb). Previous versions (don’t remember how far back) started it under the Endpoint.

So if you are using Phoenix Channels, when your channel connects, it should subscribe to changes on the models/contexts it is concerned about. Your context then broadcasts on the app pubsub (Blog.Pubsub) and the channel then maps that application pubsub to it’s channel client(s). It’s basically the same if you are using LiveView, just the LV does the subscription instead of the channel.

Chris McCord’s video intro to LiveView on the Phoenix home page explains the basic concept (it’s about mid-way through). https://youtu.be/MZvmYaFkNJI

So it’s kind of flipping what you said on its head. The client (web-side) should subscribe to the app’s pubsub topic it cares about (i.e. posts). The client manages what to do with the info it receives from the app. The app-side is only concerned about publishing on the app’s pubsub. That subscriber could be a web client, or it could be another piece of the app, or even another application that shares the cluster. So the publisher is blissfully unaware of which clients are subscribing to it and receiving the broadcasts, and even what they are going to do with that information.

The app never reaches OUT from its domain. It only broadcasts on its internal pubsub. The client-side reaches INTO the domain from the outside, just as it does when interacting with context actions, and decides what it wants notified of.

Hope that rather long-winded explanation was helpful :wink:

Also Liked

drl123

drl123

Guys, take a step back here and look at how Phoenix.PubSub is used by Phoenix. It basically is configured to be the ‘Notifier’ for the Phoenix application. When you configure the Phoenix Endpoint, you specify the pubsub (aka Notifier) to be used as MyApp.Pubsub…just as you were proposing to do with MyApp.Notifier.Phx, BUT from the other side. Now the Web side depends upon the Core and the Core is not dependent upon and unaware of the Web.

IMHO that you might be better off to just have your core application explicitly list a dependency on the phoenix_pubsub library in mix.exs, rather than have it injected by the Phoenix (Web Framework). You don’t need all of Phoenix here if you aren’t going to use it…just the pubsub library which is a standalone Hex package. Then that phoenix_pubsub library is akin to your Notifier module, but you have a one-way dependency (Web depends upon Core, Core does NOT depend upon Web).

Think of it this way: What if you wanted to use your core app with a ‘client’ other than Phoenix? Your Core would still have references to MyAppWeb.Endpoint in your proposal. Following Chris McCord’s, it would not.

The original post asked what the most idiomatic way to broadcast messages was and I would tend to trust the framework author’s methodology here! :wink:

PS…bonus points: it’s a whole lot easier to grok for someone new to your code when there isn’t that extra layer (that still has you coupled in the wrong direction)!

RudManusachi

RudManusachi

The simplest one to me is to broadcast inside Blog.create_post , but it feels that Blog shouldn’t depend on BlogWeb

I agree.

I would think: If there is only 1 place where I want to broadcast after create then, just broadcast it from there after create =)
If I find that there are multiple different places where I want to do that, then it feels like there is a need for such create_post_and_broadcast :man_shrugging:t2:

nidu

nidu

Thanks! I’m going to follow the way it’s done in the video (that’s a very good source) - use Phoenix.PubSub instead of BlogWeb.Endpoint. I guess I’ve been using Endpoint here not for it’s intended purpose.

Where Next?

Popular in Questions Top

Tee
can someone please explain to me how Enum.reduce works with maps
New
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
vac
Hi, I’m quite new in Elixir and I’m trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and I...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: The documentation above suggests that while ...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New

Other popular topics Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
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 29603 241
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
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
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement