ndrean
I am circling around with the following problem and no post helped me so far.
I have a GenServer module named MyApp.Repo here that runs GenServer.cast but GenServer.call returns an error and kills the process.
GenServer MyApp.Repo terminating
** (ArgumentError) unknown registry: MyApp.Repo
When I start the app, I check:
iex> Enum.member?(Process.registered(), MyApp.Repo)
=> true
The GenServer module MyApp.Repo is supervised as a child by the Application supervisor.
children = [
MyAppWeb.Telemetry,
{Phoenix.PubSub, name: MyApp.PubSub, adapter: Phoenix.PubSub.PG2},
MyApp.Repo,
MyAppWeb.Endpoint
...
MyApp.Repo module is a basic GenServer that registers a :name:
def start_link(),
do: GenServer.start_link(__MODULE__, [], name: __MODULE__)
def save_with_cast(user),
do: GenServer.cast(__MODULE__, {:new, user})
def save_with_call(user) do
IO.inspect(user, label: "CALL______")
GenServer.call(__MODULE__, {:new, user})
end
def handle_call({:new, user}, _from,_state) do
IO.puts("CALL______")
Phoenix.PubSub.broadcast_from(MyApp.PubSub, self(), @topic, {:perform_new, user})
{:reply, user, [])
end
def handle_cast({:new, user}, _state) do
Phoenix.PubSub.broadcast_from(MyApp.PubSub, self(), @topic, {:perform_new, user})
{:noreply, []}
end
def handle_info({:perform_new, message}, _state) do
...
MyApp.save_with_cast(user) runs :ok but not MyApp.save_with_call(user).
Trending in Questions
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
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
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
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
Documentation
While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
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
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
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
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
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
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself.
My main conc...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming











Showing Posts 11 to 20- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
al2o3cr
A general observation: if you’re ignoring the GenServer’s state in every handler, you probably don’t need a GenServer. For instance,
save_with_callcould be simplified to:As a bonus, this approach doesn’t have a single process (the GenServer) forcing everything to happen one-at-a-time.
ndrean
OK, good point, in fact, I really wondered, indeed, but how do I respond to
:perform_newif not from a Genserver? As you say, I only use the messaging part.msimonborg
You can have a GenServer (or any interested process) subscribe to and handle the messages, or a pool of them with a pool manager dispatching the messages, but you don’t need to send the messages from the GenServer if that’s all that
save_with_*is doing. You can pubsub those messages from any process and yourMyApp.Reposervers will subscribe to that topic. Then you’ll avoid routing new messages through the same process that wants to receive them, which significantly reduces the work load on each one and increases their throughput receiving the messagesndrean
Firstly apologize, just a beginner with Elixir. Then yes I believe I started with this, not using
GenServer.call. This relieves a bit of pressure but I may still need the GenServer behaviour. Nodes subscribe to this pubusub topic. Nodes also listen to:net_kernel.monitor_nodesevents, and broadcast on a:nodeupevent. I need to capture the message the nodes broadcasts and do something, so I don’t know how to do this is not using ahandle_infomatcher offered by the serverndrean
Yes, I don’t need this
handle_callindeed.msimonborg
No need to apologize! OTP takes time to learn but it’s a rewarding process.
Yes exactly, you can have a process or pool of processes on each node subscribing to the pubsub messages, even though they can be broadcasted by any caller in the cluster.
You will also need a long running process to listen for these
:nodeupevents and rebroadcast them, and any interested process can subscribe to the topic. You should probably have aNodeListenerwith the sole responsibility to handle and rebroadcast these events. All of the messages we’ve discussed so far can be handled by thehandle_info/2callback of the GenServer behaviour.You only need to
calla GenServer if it holds some state (data, connection, etc.) or performs some computation and you need the results returned. It’s always synchronous. If the calling process can do the work itself then it probably should unless you need to offload it for async behavior or error isolation, in which case you might consider spawning aTaskinstead of sending it to a single GenServer.msimonborg
A basic implementation of what I think you’re looking for
ndrean
Thanks, I refactored with your comments and challenged myself. Quite a few takeaways there. First about backpressure. Not sure to understand this term? Is this related to filling up the server’s mailbox? So you mentioned a pool of servers to push it a bit further. I will probably keep this for later as I imagine you may need libraries like Poolboy for this.
Then besides code readability or “testability”, does segregation bring better performance in terms of robustness on load? For example:
I ask these questions because concurrency between processes is a delicate topic, and reading about the usage guidelines of GenStage, again they speak about “backpressure”. Maybe some book you may recommend?
Finally, as a side comment, I noticed the catch-all clause you introduced:
handle_info(_, state), do: {:noreply, state}.LostKobrakai
Backpressure describes the act of not accepting more work before having completed previous/existing work. This allows you to prevent parts of your system from being overloaded, because at best you cannot sent them more work than they can handle. This will push work to queue up in known places where you can then deal with it.
msimonborg
I think you would also be able to implement something simple with the
PartitionSupervisorcoming in 1.14. You would have to do some hashing to make sure the messages are not duped on multiple server partitions.To me,
node upandnew userare separate topics, so by splitting them you can have other processes subscribe to one or the other in the future without coupling them togetherI put the
NodeListeneras its own process precisely because it has one responsibility. It reduces the load onRepobecauseRepodoesn’t care aboutnodedown(at least that’s what I took away from what you said). And if other processes may be interested in cluster membership, theNodeListenercan be the hub for those events for the whole node, without needing multiple processes to be subscribing tonet_kernel.monitor_nodes.If there is an error that you expect might happen and you have a way to recover from it, then I think you handle it explicitly with pattern matching. If there is a real exception with no recovery then “let it crash”, and the supervisor will restart your process at a known good state.
I added this because you said
So I assumed you were only interested in
:nodeup, not:nodedown. If you monitor nodes you will receive both, so I discarded the:nodedownmessages. Maybe that was a wrong assumption