In my erlang application i have a top level supervisor that monitors a cowboy server (gen_server):
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
init([]) ->
SupFlags = #{strategy => one_for_one,
intensity => 5,
period => 30},
ChildSpecs = [#{id => erws_server,
start => {erws_server, start_link, []},
restart => permanent}],
{ok, {SupFlags, ChildSpecs}}.`
The requests to the server can trigger the call of functions from another module, called erws_auction_agent. Inside this module, when a certain request is received, it executes the spawn of a new process that has to handle the request (an auction in this case):
AuctionPid = spawn(fun() -> auction_handle(PhoneName, MinimumPrice, AuctionTime, EndDate) end)
The auction_handle function has to basically wait for erlang messages and perform different operations depending on the message:
auction_handle(Phone, Bid, AuctionTime, EndDate) ->
receive
%% Receive JOIN request from a Bidder
{bidder_join, PhoneName} ->
RemainingTime = get_time_remaining(EndDate),
CurrentWinner = erws_mnesia:get_winner_bidder(PhoneName),
case CurrentWinner of
{WinnerEmail, _} ->
gproc:send({p, l, {?MODULE, PhoneName}}, {joined, Bid, RemainingTime, WinnerEmail});
not_found ->
gproc:send({p, l, {?MODULE, PhoneName}}, {joined, Bid, RemainingTime, []})
end,
auction_handle(Phone, Bid, EndDate - erlang:system_time(second), EndDate);
... other cases
end.
I thought that could be a good idea to have a supervisor also for these processes, that are added dynamically. I tried both adding them to the already present supervisor and creating another supervisor started from the higher level one, but got the same error, related to child specification. For instance, i tried adding the child to the top level supervisor by calling this function from it:
start_auction_process(PhoneName, MinimumPrice, AuctionTime, EndDate) ->
{ok, AuctionPid} = supervisor:start_child(?SERVER,
[#{id => PhoneName,
start => {erws_auction_agent, auction_handle, [PhoneName, MinimumPrice, AuctionTime, EndDate]},
restart => transient}]),
AuctionPid.
The error I get is the following:
{error,
{invalid_child_spec,
[#{id => <<"Sony Xperia Pro">>, restart => transient,
start =>
{erws_auction_agent,auction_handle,
[<<"Sony Xperia Pro">>, 1, 240,
1714667160]}}]}}
What am I doing wrong? Which can be the best approach to use in this case? Do i need to have a separate gen_server for the handle_auction logic? Thanks in advance.
supervisor:start_child/2 is defined like so:
start_child(SupRef, ChildSpec) -> startchild_ret()
where ChildSpec is of type:
child_spec() | (List :: [term()])
And child_spec() is defined to be:
#{stuff in here} OR {stuff in here}
All together, ChildSpec can be:
#{stuff in here} OR {stuff in here} OR [stuff in here]
Instead of this:
start_auction_process(PhoneName, MinimumPrice, AuctionTime, EndDate) ->
{ok, AuctionPid} = supervisor:start_child(?SERVER,
[#{id => PhoneName,
start => {erws_auction_agent, auction_handle, [PhoneName, MinimumPrice, AuctionTime, EndDate]},
restart => transient}]),
try:
start_auction_process(PhoneName, MinimumPrice, AuctionTime, EndDate) ->
{ok, AuctionPid} = supervisor:start_child(
?SERVER,
#{
id => PhoneName,
start => {erws_auction_agent, auction_handle, [PhoneName, MinimumPrice, AuctionTime, EndDate]},
restart => transient
}
),