sezaru

sezaru

Fastest way to a GenServer communicate with all childrens of some supervisor?

Hello,

A part of my application currently have a supervisor hierarchy that looks something like this:

As you can see, I have a Manager Genserver and a Childs Supervisor that will contain a lot of children’s (this is a normal supervisor for now, but maybe in the future I would want to start the children on demand, so that can be changed to a Dynamic Supervisor in the future I guess).

My question is regarding the Manager Genserver communication with the children’s. Basically Manager Genserver needs to send broadcast messages to all the children’s, this can happen very frequently (like multiple times a second), so I have a performance concern.

So, what kind of communication strategy should I use in this case? I’m kinda new with OTP, so I’m not 100% sure and are contemplating the following solutions:

  1. Create a function inside Childs Supervisor that will iterate and do a GenServer.call to all it’s children. Not sure if this is efficient or will bottleneck all the communication if one children blocks the call for some reason;

  2. Send a message from each Child to the Manager GenServer with it’s PID, store it in a list and send GenServer.call iterating through it;

  3. Use a PubSub system like Phoenix.PubSub. This seems like a good solution, but as far as I know the Phoenix.PubSub is global and used more for a distributed case. I’m not sure if using it would be over-engineering and maybe be a bottleneck;

  4. Use the Registry. this seems like another good solution too but I only saw examples of global (but local to the beam node) examples of Registry, in my case I only want to handle communication from Manager Genserver to all the Childs, is it possible to create maybe a local Registry for Parent Supervisor?

Any help would be much appreciated.

Thanks a lot!

Most Liked

kokolegorille

kokolegorille

Supervisor has the which children function (and more…)

You should try to benchmark if sending message to that list of children is within your refresh frequency.

lud

lud

Your 1) timeouts because you implemented it inside a handle_call and call it from another process. But this problem is out of scope. You could add a :infinity timeout.

You could call all children concurrently:

    reply = state.childs
    |> Map.values()
    |> Enum.map(fn pid -> Task.async(fn -> GenServer.call(pid, {:received_msg, "hello"}) end) end)
    |> Enum.map(&Task.await/1)

Edit: but this is a poor man’s implementation of GenServer.multi_call.

Or use Task.async_stream to limit the number of concurrent calls.

Calling your children with GenServer.call provides another guarantee : all calls will be made before you start to call your children again. The other solutions do not give this guarantee. But you may not care about it.

Where Next?

Popular in Questions Top

New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> somethi...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
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
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
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
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
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New

Other popular topics Top

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
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
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
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
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
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
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
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement