venomnert
Creating process from GenServer and passing state
Context:
I am pretty new to OTP. In trying to learn it I’m creating an application that does the following (high level overview):
- users submit X number tasks to a GenServer.
- The GenServer iterates over the queue of tasks and creates a process for each task.
- Once the process is completed it will notify the GenServer it’s done and return its value.
- Once the GenServer get’s notified it will update the state with the process’s return value, and notify the client with the updated state.
The diagram demonstrates what I’m trying to achieve.
I am able to spawn a process from the GenServer; however, I’m struggling to connect between the GenServer and process, so the process can call the GenServer; in return, the GenServer can handle_call/3.
Questions:
- Am I taking the right approach of calling a process from a GenServer? Is there better way to create process from GenServer and notify the process about the state?
- How do I call GenServer from a process and passing the state to server?
Marked As Solved
al2o3cr
This sounds a lot like the Task functionality in the Elixir standard library. Here’s some relevant discussion from 2018, complete with a code example:
The tricky part with spawning additional processes is making sure everything works sensibly when things go wrong - what happens when those processes shut down, when the parent shuts down, etc. The Task library wraps the relevant parts (linking, supervising and so on).
Also Liked
joaquinalcerro
Even though this code might work for your current use case you have to consider what happens if one of the tasks crashes.
With this code, if one task crashes, your GenServer will also crash with your state because the Task is still sending the GenServer a message that is currently not handled. You can handle them as follows:
def handle_info({:EXIT, _task, _reason}, state) do
IO.puts("Crashed!!!!!")
{:noreply, state}
end
def handle_info({:DOWN, _ref, :process, _pid, reason}, state) do
IO.inspect(reason)
{:noreply, state}
end
The first message will have the tuple {:EXIT, task, reason}. The other one is {:DOWN, _ref, :process, _pid, reason}. You already have a tuple similar to this one but handles the happy path when the task exits normally like this {:DOWN, _ref, :process, _pid, :normal}… note the :normal atom at the end will be pattern matched.
With this in place, your GenServer will not crash and will be available to handle other tasks.
So this might work but: I just wanted to share with you some recommendations @whatyouhide gave us during this weeks ElixirConfLA in Medellin.
He recommended us:
-
Limit the amount of tasks that can be spawned to avoid exhausting the resources
-
Use the proper strategy for your use case:
a. one_to_one
b. one_for_all
c. rest_for_oneSo what happens if one of the task fails? is it worth continue processing the other tasks? how will your state be affected if one task fails?
Check this link for details of each one: Supervisor — Elixir v1.20.2
-
Nest you supervision tree with other supervisors with the proper strategy. For example, under your main application supervisor, create a worker supervisor with a one_for_one strategy.
-
All processes should be supervised
-
Name your supervisors to access them by name which is easier.
-
Test you supervision tree
I will be monitoring when the talks are published to link it to this thread.
Best regards,
Popular in Questions
Other popular topics
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
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









