lalo2302
Hi guys!
I am facing a problem where I need to spawn multiple processes, and I have to keep a counter about every process. The counter needs to be indepent and accesing it should not interfiere with the process performance.
Saying this, I am exploring the options of Agent vs Registry.
If I use the Agent module, I would register an Agent for each process :via a Registry.
But how should this be different from only using a Registry, with the register function and the counter as a value.
Isn’t a registry the same as an Agent in that case?
Later today I’ll benchmark it, but wanted to know what do you think. I’ll post my results below.
Have a nice day!
Trending in Questions
Hello!
Suppose you are building workflow (order / task / payment) processing system with the following requirements:
Each workflow con...
New
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
Hey guys,
I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly
Do you guys have any suggestions what is the best prac...
New
Kia ora,
We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
I’ve followed the Phoenix LiveView file upload code here Uploads — Phoenix LiveView v1.0.0-rc.7 and so far everything works just fine wit...
New
Hello,
I’m developing a online persistent chat system (what’s app) like using elixir/dynamodb/aws for a mobile app(flutter).
The diffic...
New
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
Other Trending Topics
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
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #ai
- #phoenix_html
- #iex
- #elixirconf-us
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
peerreynders
I think the answer to your problem is another process which is only responsible for the counter.
Alternately it may make more sense for the counter process to be subscription based - otherwise you are building an “ask architecture” rather than a “tell architecture” (Tell, Don’t Ask).
Personally Agents make me queasy because anybody can mess with their internal state which has the smell of “global mutability”.
Registry pubsub may be an interesting option - though I haven’t looked at it in detail (if I’m reading the source correctly,
dispatch/4will run in the calling process rather than queuing the function to be executed later within the registry’s process, so I would classify this approach as “interfering with process performance”).CptnKirk
I’m not exactly sure what you mean here. Do you mean that you need to keep a total count of your workers? Or that each worker needs to keep an independent counter of something?
If you simply need to keep track of your worker totals, you might consider using a custom Supervisor or DynamicSupervisor. You’d use the Supervisor to spawn and watch your workers for failures. Supervisors also keep a count of their children, so you’d get a global worker count for free, without impacting the work being done within the workers.
Supervisors - spawn and monitor children for failures, restarting them if necessary
Agents - store and mutate local state
Registries - keep track of a mapping from a name → pid
Both Registries and Supervisors support a count. Supervisors will help you keep your workers alive. Registries will help you find and communicate with multiple workers. However, if a worker dies, it’ll be removed from the registry without any attempts at restarting.
lalo2302
No, I mean the spawned process will do something, but only accepts more work if it is doing less than a number a things. Like a queue, if the queue of the process work exceeds certain amount, it should reject the request. And I need to keep count of the length of the queue.
The mailbox queue length is my counter.
So my options are:
And now that I’m writing this, I could use
Process.info(pid, :message_queue_len)before sending a message with work to the process. But then I’m not really sure how to test the genserver to see if it accepts more message after a limit. If I send unexpected messages, the test logs:received unexpected message in handle_info/2:which is not nicelalo2302
I saw
dispatch/4but as your edits says, it may interfere with the process performance. Thank you for the link on Tell, Don’t Ask, was a great reading. With that I may refactor a little bit of what I’ve done.LostKobrakai
This sounds like a job for GenStage and not the mailbox queue.
OvermindDL1
I’d use either ETS or gproc, probably gproc as it can link counters existence to a process as well.
peerreynders
It may make more sense to organize it a bit differently along the lines of Building Non Blocking Erlang apps:
GenStage.ConsumerSupervisordoes something similar but you may need a solution adapted to your particular requirements. Also have a look atTask.Supervisorjust so you know what is available.CptnKirk
I would also recommend looking into GenStage for this. You don’t have a tell/ask problem. You want to limit the rate at which you get told something to the amount of capacity you have to process those tells.
This is what GenStage does. You advertise that you’re able to handle some number of events, and then you eventually get at most that number. Once you decide you can handle more events, you advertise that you’re able to handle more. This is all done more or less transparently for you by GenStage.
As you’ve already discovered, architecting a solution to your problem with Process.info doesn’t work well.
Consider using GenStage to solve your rate problem. Then within GenStage, delegate to a module that is focused on data processing. This way you’ve separated your business problem from your rate problem. And you can test your business module easily.
Agents and Registries aren’t required here. Although you’re free to register your GenStage processes with a Registry and/or hold state within an Agent. Up to you, they are different tools for different problems.
Edit: You may also want to look at Flow. Flow helps to provide a higher level data flow/processing abstraction, so you don’t need to worry about implementing a GenStage. If your workers are mapping or reducing something, then Flow could be a great fit.
lalo2302
As I undertand it. The producer would hold events until the consumer asks for them. But I would need the producer to reject any more events and return an error to the client. This is why I don’t see how GenStage can help me.
I am reading about all the suggestions.
Thank you all for everything.
josevalim
You are already making a big assumption that you will need processes. Could you please tell us about the problem you want to solve in general and why did you arrive to the conclusion that you need processes?
Why are you keeping count of how much work a process has done? Why not have a single process that does a single work and then dies?