voger

voger

Question about code from The Little Elixir & OTP Guidebook

I apologize in advance if this is not the proper place to ask questions about code from books but I don’t know where else to ask and I believe a lot of people here have read it and will be familiar with the code. If there is a more appropriate place please point me there.

Here is the question:

In chapter 6 the author creates a worker supervisor with this code

def init({m, f, a} = x) do
	worker_opts = [restart: :permanent,
								 function: f]
	children = [worker(m, a, worker_opts)]

	opts = [strategy: :simple_one_for_one,
					max_restarts: 5,
					max_seconds: 5
	]

	supervise(children, opts)
end

and in chapter 7 he creates a handle_info function in the server.ex and sets the server to :trap_exit, true

def handle_info({:EXIT, pid, _reason}, state = %{monitors: monitors, workers: workers, worker_sup: worker_sup}) do
    case :ets.lookup(monitors, pid) do
      [{pid, ref}] ->
        true = Process.demonitor(ref)
        true = :ets.delete(monitors, pid)
        new_state = %{state | workers: [new_worker(worker_sup)|workers]}
        {:noreply, new_state}

      [] ->
        {:noreply, state}
    end
    {:noreply, state}
  end

 defp new_worker(sup) do
   {:ok, worker} = Supervisor.start_child(sup, [[]])
   Process.link(worker)
   worker
 end

I don’t understand why we need to create a new worker process in this line in handle_info

new_state = %{state | workers: [new_worker(worker_sup)|workers]}

Since the worker has a restart: :permanent option and the supervisor has a strategy: simple_one_for_one the crashed worker will restart anyway. Why do we need a call to Supervisor.start_child(sup, [[]])

Let’s say we start with 5 workers. We crash one. Because of strategy: simple_one_for_one we get a new worker. Then we call Supervisor.start_child(sup, [[]]). Wouldn’t this give us a 6th worker? I know it doesn’t but why?

A theory I have is: because of the handle_info(:EXIT, ... the server is first to handle the crash, before the supervisor has a chance to do anything. When it comes the supervisor’s turn, it sees that it still monitors 5 workers so it’s all good.

UPDATE: I tried to set the restart options to restart: :temporary for the worker and this time no new process replaced the crashed process even though Supervisor.start_child is called. So my theory doesn’t hold.

UPDATE 2: I tried also returning simply {:noreply, state } (without %{state | workers: [new_worker(worker_sup)|workers]}) and the process still gets re spawned.

Most Liked

voger

voger

:EXIT and :DOWN do not differentiate forced or normal exits but links and monitors. In that code :DOWN is used to monitor the client process. The one who requested one of our worker processes from the pool.

wfgilman

wfgilman

I thought the :EXIT signal was for a process that exited safely, not a crash. In that case the supervisor wouldn’t restart the child. I thought :DOWN was for unexpected terminations and the supervisor would restart those processes.

Where Next?

Popular in Questions Top

aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> somethi...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
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
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
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
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
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
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 43487 311
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
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
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement