Question

I define simple_one_for_one worker spec for one supervisor named band_supervisor, and the child spec id is jam_musician:

  init([]) ->
    {ok, {{simple_one_for_one, 3, 60},
    [{jam_musician,
    {musicians, start_link, []},
    temporary, 1000, worker, [musicians]}
    ]}};

musicians module is:

-module(musicians).
-behaviour(gen_server).

-export([start_link/2, stop/1]).
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, code_change/3, terminate/2]).

-record(state, {name="", role, skill=good}).
-define(DELAY, 750).

start_link(Role, Skill) ->
  gen_server:start_link({local, Role}, ?MODULE, [Role, Skill], []).

stop(Role) -> gen_server:call(Role, stop).

and I can create many workers by:

3> supervisor:start_child(band_supervisor, [drum, good]).
Musician Arnold Ramon, playing the drum entered the room
{ok,<0.696.0>}
3> supervisor:start_child(band_supervisor, [guitar, good]).
Musician Wanda Perlstein, playing the guitar entered the room
{ok,<0.698.0>}

I notice that all workers have the same Child spec Id: jam_musician

You know other type workers must has the unique child id, Right ?

Was it helpful?

Solution 2

The child specification identifier will be the same for simple_one_for_one supervisors since there is only one child type and many child instances (workers) of this type.

From the supervisor behaviour docs:

Notice that when the restart strategy is simple_one_for_one, the list of child specifications must be a list with one child specification only. (The child specification identifier is ignored.) No child process is then started during the initialization phase, but all children are assumed to be started dynamically using start_child/2.

OTHER TIPS

Most likely you wrote the start_link function of the child process (I assume it is a gen_server) as:

start_link() ->
    gen_server:start_link({local,Name}, ?MODULE, [], []).

This not only calls the init/1 function but also registers the process using the atom Name.

Therefore any new child started in a second moment will try to register inside the erlang node using a name already taken by the first child.

In order to avoid such name clashing you should use something like:

start_link() ->
    gen_server:start_link(?MODULE, [], []).

So that no child will have a registered name and you will have no clashing.

If you really need to register every child an option may consist in the use of gproc.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top