elixir-lang / elixir

Elixir is a dynamic, functional language for building scalable and maintainable applications

Home Page:https://elixir-lang.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DynamicSupervisor: the option "max_restarts" only work if provided as initial argument

JoeZ99 opened this issue · comments

Elixir and Erlang/OTP versions

elixir 15.4
otp 26

Operating system

linux

Current behavior

When specifying the "max_restarts" option as a regular when using DynamicSupervisor, it doesn't work.

How to check?

Have this two modules:

defmodule Test2 do             
  use GenServer                                                                                                                         
                                                                                                                                                    
  def start_link(_opts \\ []) do                                                                                                    
    GenServer.start_link(__MODULE__, [])                                                                                            
  end                                                                                                                               
                                                                                                                                    
  def init(_opts \\ []) do     
    Process.send_after(self(), :boom, 2000)    
    {:ok, :ok}                                                                                           
  end                          
                                                                                                                                                                               
  def handle_info(:boom, _), do: raise "Boom!"    
end  

and

defmodule Pipo do              
  def start(options_mr, args_mr) do                                                                                                     
    do_start(options_mr, args_mr)                                                                                                                   
  end                                                                                                                               
                                                                                                                                    
  @impl true                                                                                                                        
  def init(args_mr) do                                                                                                              
    DynamicSupervisor.init(max_restarts: args_mr, strategy: :one_for_one, max_seconds: 10)    
  end                                          
                                                                                                         
  def add_children do          
    DynamicSupervisor.start_child(__MODULE__, Test2)                                                                                                                           
  end                                             
                                                                                                         
  defp do_start(options_mr, args_mr) do    
    DynamicSupervisor.start_link(__MODULE__, args_mr, name: __MODULE__, max_restarts: options_mr)    
  end    
end    

an then on a shell, do:

iex> Pipo.start(100,3)
iex> Pipo.add_children

and you'll see how it explodes only three times (because after 3 restarts, the dynamicsupervisor dies), in spite of you specifying "100" restarts in the options

however, if you do:

iex> Pipo.start(3, 100)
iex> Pipo.add_children

you'll see it restarts the children more than three times.

Expected behavior

Based on documentation, I expect that providing max_restarts as regular option:

DynamicSupervisor.start_link(__MODULE__, _init_args, max_restarts: 100)

would work

But only work if provided as initial option:

DynamicSupervisor.init(max_restarts: 100)

For clarity, Can you please link to the documentation that implied max_restarts work on start_link/3? Thank you!

@josevalim, I think it comes from

@spec start_link([option() | init_option()]) :: Supervisor.on_start()

where :max_restarts is indeed seen as an init_option() element: https://hexdocs.pm/elixir/1.17.1/DynamicSupervisor.html#start_link/1

But that’s start_link/1, right?

But that’s start_link/1, right?

You're right. I mis-read it 😄 Maybe the OP did too 🤷 😄 Sorry for the noise.

Well, it's not so much a bug or a bad doc, but more like it's easy to confuse option with init_option in the docs, and the confusion of @paulo-ferraz-oliveira is a perfect example of that...

First and foremost, the people from https://github.com/arjan/singleton has suffered the same confusion (in fact, that's how I got -after 2 weeks- to nail this 😄 ), if you look at https://github.com/arjan/singleton/blob/master/lib/singleton/supervisor.ex#L25 and https://github.com/arjan/singleton/blob/master/lib/singleton/supervisor.ex#L25, you'll see that they intend to use max_restarts as an option to be passed to start_link/3

I've tried to read about it in the docs, and I find it at least slightly misleading...

So, in a nutshell, I can't exactly "blame" the doc, but I think it's very easy to get confused and assume option and init_option are the same, and I'd rather be more explicit about the difference on init_option and option, which now can only be perceived if you link in the specs ....

Hi @JoeZ99! No worries, we can totally blame the docs! They can always improve and that's the biggest question: how could we improve them? Would you like to try a PR? I would be glad to review it.

hey @josevalim , txs!!!

I've made a PR: #13678, but I don't know what else to do ... Another thing is that this "doc improvement" is to be read at least since version 1.15.4 of elixir, I don't know if I should make a PR for that tag and every subsequent one ...

But that’s start_link/1, right?

You're right. I mis-read it 😄 Maybe the OP did too 🤷 😄 Sorry for the noise.

what does "OP" mean 😄 ????

I believe it means "Original Poster", so it was referring to you. :)