Как запустить супервизор с воркерами, которые не являются gen_servers?

Здравствуйте, я пытаюсь запустить supervisor, чьи рабочие не gen_server (s). Мой супервизор для краткости определен в том же модуле, что и рабочий:

Я продолжаю получать эту ошибку, и я попытался поместить атрибут MFA в [ ], но безрезультатно. Я также поместил ChildSpec в [ ]. Что мне не хватает?

Я не хочу, чтобы у моего руководителя были работники при запуске.

Ошибка

>  X=sup:start_link().
> ** exception error: no match of right hand side value {error,
>                                                        {bad_start_spec,[]}}
>      in function  sup:start_link/0 (c:/Erlang/ProcessPool/sup.erl, line 6)
> =CRASH REPORT==== 5-Apr-2020::22:20:32.918000 ===   crasher:
>     initial call: supervisor:sup/1
>     pid: <0.280.0>
>     registered_name: []
>     exception exit: {bad_start_spec,[]}
>       in function  gen_server:init_it/6 (gen_server.erl, line 358)
>     ancestors: [<0.273.0>]
>     message_queue_len: 0
>     messages: []
>     links: [<0.273.0>]
>     dictionary: []
>     trap_exit: true
>     status: running
>     heap_size: 376
>     stack_size: 27
>     reductions: 205   neighbours:

Модуль

-module(sup).
-behaviour(supervisor).
-compile([export_all]).

start_link() ->
     {ok, Pid} = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
     Pid.

init(_Args) ->
     RestartStrategy = {simple_one_for_one, 10, 60},
    {ok, {RestartStrategy,[]}}.

add(Sup,Value)->                #adding child
    ChildSpec = {
                  ch1, 
                  {sup, start, [Value]},
                  permanent,
                  brutal_kill, 
                  worker, 
                  [ch1]
                },
    supervisor:start_child(Sup,ChildSpec).


start([Value])->                                    #child's start_link equivalent (non-genserver)
    spawn_link(?MODULE,initworker,[self(),Value]).

initworker(From,Value)->                            #child's init
    receive 
       MSG->From ! {got_msg,Value,MSG}
    end.

person Bercovici Adrian    schedule 05.04.2020    source источник


Ответы (1)


Поскольку вы используете simple_one_for_one, вы должны определить ChildSpec в init, и все дочерние элементы будут использовать один и тот же ChildSpec.

Если вам нужно другое, используйте вместо этого стратегию one_for_one.

Для simple_one_for_one:

Второй аргумент supervisor:start_child/2 должен быть списком, который будет объединен с аргументами по умолчанию для аргументов дочерней функции запуска, определенных в ChildSpec.

Здесь я быстро изменил код, чтобы он работал на вас.

-module(sup).
-behaviour(supervisor).
-compile([export_all]).

start_link() ->
     {ok, Pid} = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
     Pid.

init(_Args) ->
     RestartStrategy = {simple_one_for_one, 10, 60},
     ChildSpec = {
                  ch1, 
                  {sup, start, []},
                  permanent,
                  brutal_kill, 
                  worker,
                  [sup]
                },
    {ok, {RestartStrategy,[ChildSpec]}}.

add(Sup,Value)->                
    supervisor:start_child(Sup,[Value]).


start(Value)->                                    
    P = spawn(?MODULE, initworker,[]),
    P!{self(),Value},
    {ok,P}.

initworker()->                            
    receive 
       {From, MSG} -> io:format(" Value is ~p~n", [MSG])
    end.
person Adinarayana Immidisetti    schedule 06.04.2020
comment
Я не понимаю. Нельзя ли добавить ChildSpec после init? Я имею в виду, что когда я использую supervisor:start_child, я не могу установить его дочернюю спецификацию? Должен ли супервизор знать спецификацию перед добавлением какого-либо дочернего элемента? - person Bercovici Adrian; 07.04.2020
comment
Запуск дочернего элемента с другим кодом противоречит принципу работы супервизоров simple_one_for_one. Пожалуйста, проверьте документ здесь erlang.org/doc/man/supervisor.html#check_childspecs -1. Как указано в моем ответе, вы можете попробовать индивидуальный супервизор иметь ChildSpec после инициализации. дополнительная информация: stackoverflow .com / questions / 11120207 / stackoverflow.com/questions/41190705/ - person Adinarayana Immidisetti; 07.04.2020
comment
Хорошо, но есть ли способ вставить данные из моего ChildSpec в каждый дочерний элемент, который впоследствии будет порожден? В моем примере id хотел бы добавить некоторые аргументы в MFA из init(), которые будут переданы всем добавленным дочерним элементам. - person Bercovici Adrian; 07.04.2020
comment
Если вам нужен ChildSpec после инициализации. Измените код, чтобы использовать one_for_one вот так. codepile.net/pile/0zeJrpow или выше код в ответе также может добавлять аргумент динамически, если вы вызовите sup: add (sup: start_link (), newargument). - person Adinarayana Immidisetti; 07.04.2020