bartblast

bartblast

Creator of Hologram

Time to Implement Pub/Sub in Hologram - Looking for Your Input!

With the core component system and HTTP/WebSocket infrastructure solid, it’s time to tackle Pub/Sub support.

What We Have vs What’s Missing

Currently: Actions, Commands, WebSockets and HTTP transport, component communication

Missing: Real-time server-initiated updates

I Want Your Input First

I have ideas about how Pub/Sub should work in Hologram, but I want to hear from you before biasing the discussion.

How would you want to use Pub/Sub?

  • API design and DSL preferences (Phoenix PubSub-like? Something else? etc.)
  • Component/Page integration (how should subscriptions work?)
  • Use cases (chat, notifications, live dashboards, collaboration, etc.)

Thanks for helping shape this!

Most Liked

garrison

garrison

I would strongly favor a declarative sync-based API for tracking server state on the client. I don’t know exactly how this would look (nor do I have a great understanding of Hologram’s existing APIs). But using Phoenix terminology, some way to specify that a given set of assigns should be automatically shipped to the client and kept up to date (with no tearing) would be a good path, I think.

I would not recommend venturing down the path of encouraging developers to maintain synchronization with their own imperative “glue” protocol (i.e. sending their own diffs down the wire by hand). This always ends badly.

kingdomcoder

kingdomcoder

Hi, @bartblast

I think of PubSub in Hologram the same way I think of events—they’re triggers (that sometimes carry data). These server-side “events” can be similarly bound to actions/commands, and the rest of the Hologram plumbing immediately becomes available to us. I imagine new server-side functions put_pubsub and delete_pubsub as the main additions.

Add a Subscription

To subscribe to a PubSub channel, call put_pubsub in init/3 or command/3:

put_pubsub(server, pubsub_channel, command: :my_command)

or

put_pubsub(server, pubsub_channel, action: :my_action)

Delete a Subscription

To unsubscribe from a PubSub channel, call delete_pubsub in command/3:

delete_pubsub(server, pubsub_channel)

or

delete_pubsub(server, pubsub_channel)

I suggest there should also be a cleanup mechanism that unsubscribes when a component is removed from the page.

To Handle a Message

Each time a pubsub message is received, its corresponding command/action is triggered and can be handled as such:

def command(:my_command, pubsub_msg, server) do
  # do something with the message
end
def action(:my_action, pubsub_msg, component) do
  # do something with the message
end

Additionally, I don’t think PubSub handling should be restricted to pages. This is one of the banes I have with LiveView where handle_info is available only in the LiveView and not in LiveComponents. Each component should be able to call put_pubsub and delete_pubsub in its own init/3 and command/3 functions.

Finally, I wouldn’t recommend adding a target option to put_pubsub where a subscription in one page/component can trigger a command or action in another. Each page/component should subscribe independently to a channel if it needs to react to messages. This is not a “hard” suggestion, but I think it will help avoid confusion.

PS: Thank you for always welcoming input from the community. We’re grateful for your hard work :clap: :clap:

bartblast

bartblast

Creator of Hologram

Thanks everyone! I love how we’ve accidentally created a buffet of real-time patterns :smiley:

If I understood correctly:

  • @Eiji proposed process messaging (very Elixir-native!)
  • @garrison proposed state sync (declarative and clean)
  • @jam proposed reactive queries (ambitious and exciting - I’d definitely like to explore the local-first path you showcased! I have something similar in mind for next stages)

All fascinating approaches, but I should clarify - I’m specifically looking for Pub/Sub (Publish/Subscribe) patterns. Think broadcasting messages across channels/topics like Phoenix Channels and Phoenix PubSub, but reimagined for ideal DX.

The exciting part: Hologram could eventually work across clusters of devices (web/mobile/desktop), so we could target specific users, sessions, or even component IDs (cids). We could broadcast to “all users in room X,” “session Y,” or “component Z on any device.”. Eventually… :wink: For now let’s just make it work for common cases.

Forget implementation details or what Phoenix did - what would the ideal developer experience look like for publishing/subscribing to messages across this kind of distributed component system?

Let’s get creative! :rocket:

ken-kost

ken-kost

I trust your ideas will be great, since the DX for hologram in general feels great. My use case would be your example of svg drawing from 0.5.0 release - I want to broadcast changes to other players in the room. I’m making a scribble game in your framework - it’s fun! This is my missing piece. :ogre:

Eiji

Eiji

I would say that at least for now you should go the “safe way” and implement Pub/Sub that is very similar to the phoenix one. Of course some framework-related things have to be adjusted (actions vs handle_* functions), but I would rather stay with similar naming concept simply to make migrating existing applications to Hologram as simple as possible.

I think that’s fastest way, best for initial adoption and does not block possible alternative solutions in future. Maybe a good point would be to release it as hologram_pubsub, so it’s not considered as a part of the core and could be easily replaced only by updating generators (if any) and guides.

Where Next?

Popular in Discussions Top

cjbottaro
I’ve been primarily doing Elixir development for the past 6 years or so, and during that time whole heartedly committed to functional par...
New
fklement
This is a thread to gather some information about the efforts of using elixir in combination with cars or vehicular systems in general. ...
New
adamu
When starting a new project, do you have any go-to libraries you pull in out of habit/preference? For example, Ash, Credo, Mox, ExMachin...
New
AstonJ
Phil just posted this on EFS: …interesting that some of the key updates to JavaScript appear heavily influenced by (or blatantly copied...
New
bglusman
I’m curious how others in the community deal with first class enums… especially crossing boundaries like database, code logic, and absin...
New
tristan
First announced on the Erlang Forum, BEAMup is a tool for installing a managing the active instance of BEAM languages. It has support for...
New
arcanemachine
Just wondering what the community currently thinks, prefers, and/or recommends for working with UI components. (e.g. daisyUI, MishkaChele...
New
bartblast
Added by a user on X: https://x.com/aldicodes/status/1952095492139299036
New
dogweather
I’ve been brainstorming about ways to solve the N-dimensional code organization problem, and am thinking about developing a Smalltalk-lik...
New
travisf
In upgrading from Ecto 2 to Ecto 3 I’m dealing with a failing test. If I use ExMachina build(:address) I’ll get an error trying to put_e...
New

Other popular topics Top

9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New

We're in Beta

About us Mission Statement