forte

forte

Hi, I have a question regarding the Phoenix PubSub process as it’s used by Channel sockets. Are the sockets that receive broadcast! messages via the PubSub process guaranteed to receive and handle messages sent to the PubSub process (via broadcast!) in the order that the PubSub process received them?

I’m assuming that since there’s only one PubSub process then there’s no opportunity for, say, 2 messages each sent via broadcast! in 2 seperate socket processes, one at time = T1 and the other at T2, to be received by sockets subscribed to the PubSub out of order (say T2 and then T1).

Thanks.

Showing Posts 1 to 8

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

There is no global pubsub process. The VM guarantees message order for any messages sent between two process. So, if process A sends process B, :foo and then :bar, process B is guaranteed to receive them in that order. However if A sends :foo to B and then C sends :bar to B, it’s possible it could see them in any order, depending on how close together those sends happened.

When you broadcast!("some topic", value) you are basically acting as Process A, and you are sending to all processes that are subscribed to that topic. So, if you broadcast :foo and then broadcast :bar, that will arrive in the correct order to everyone.

forte

forte OP

Thanks @benwilson512. I saw a PubSub.local0 genserver process in the erlang observer process tree and thought maybe it was “sending” messages to the socket processes I saw it was monitoring. But that’s not very elixir-ey. If anything, that PubSub process (or some other entity) would probably keep a registry of socket genserver pids within which broadcast! calls would ultimately call functions.

All that aside, I think I get it. Thanks a lot.

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Ah yeah so those are mostly for managing the :ets tables that hold onto the pubsub registration information. There are also some processes used for forwarding pubsub messages between nodes in a distributed erlang scenario. There are definitely processes used in Phoenix PubSub internals, I guess I mostly wanted to point out that there isn’t some singular process, or even a singular process per topic that serializes messages in a global way.

forte

forte OP

Gotcha - yeah I was initially asking the question as if there were some PubSub queue process or something like that, and what I’ve gotten from this is that there definitely is not. Thanks.

forte

forte OP

I’ve had a bit of time to collect my thoughts and I’ve got another related question.

  • Say you have socket procs A, B, C, D

  • These procs can both send and receive messages

  • PubSub happens by a socket proc sending another proc a broadcast message, there is no global PubSub “queue”

  • if A sends message :foo to the rest, and D sends :bar immediately afterwards, A will iterate through the list of subscriber procs [A, B, C, D] in order and send its message, and D will do the same.

  • since the list of subscribers is I’m sure always in the same order, I can’t imagine that C, for example, would ever receive D’s message before A’s.

Or would it? The only way that would be possible is if the BEAM scheduler interleaved the execution of A and D’s message sending unevenly, or if A and D were operating on different cores and actual parallelism was happening.

Ultimately what I’m worried about is I want to be sure that the subscribers to topics (and ultimately the users consuming this all in the web browser) all get their events in the same order. I don’t care if A clobbers D, I just want to ensure they all have a consistent state. Imagine 4 users corresponding to the 4 procs mentioned above. If 2 users (proc A’s and proc D’s) each entered a different value in a text box in a browser that was sent to all 4 users via websockets, I don’t care which value they all receive last - i.e. which one “wins” - I just want them all to have the same value. Does Phoenix Channels guarantee that?

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

it 100% can happen in not the order you expect, particularly if A and D are on different servers.

No, this is a distributed state issue. You either need to bring your own coordinating entity, or use something like a CRDT. This latter thing is actually what Phoenix Presence does, although it is by no means simple.

forte

forte OP

Thanks @benwilson512. Is the problem exacerbated when A and D are on different servers, or only possible when they’re on different servers?

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Exacerbated, but it’s 100% possible even with one server for a variety of reasons.

For one thing, this ^ is a flawed assumption. Subscribers are stored in Registry, which uses a sharded set of :ets tables in :duplicate_bag mode. There is no real order guarantee here at all between any two invocations, plus the list itself can change between those invocations in a way that may effect the order.

Even if the order was a simple list somewhere, the BEAM simply doesn’t provide the guarantee you’re looking for. If the time between A and D messaging C is sufficiently small, then small differences like which scheduler each process is currently on can cause them to arrive out of order. Message order is only guaranteed between one process and another.

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews