Current section
Files
Jump to
Current section
Files
src/runtime/tasks/adk_task_sup.erl
%% @doc Dynamic supervisor for bounded, independently owned tasks.
-module(adk_task_sup).
-behaviour(supervisor).
-export([start_link/0, child_spec/1, start_task/3]).
-export([init/1]).
-define(SERVER, ?MODULE).
-spec start_link() -> supervisor:startlink_ret().
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
-spec child_spec(term()) -> supervisor:child_spec().
child_spec(_Opts) ->
#{id => ?MODULE,
start => {?MODULE, start_link, []},
restart => permanent,
shutdown => infinity,
type => supervisor,
modules => [?MODULE]}.
-spec start_task(binary(), fun(() -> term()) | {module(), atom(), [term()]},
map()) -> supervisor:startchild_ret().
start_task(TaskRef, Work, Opts)
when is_binary(TaskRef), is_map(Opts) ->
%% Dynamic child MFAs are included in supervisor reports. Start an empty
%% worker with only its random public reference, then synchronously perform
%% a one-shot handoff. Work and options never enter supervisor state.
ChildSpec = #{id => TaskRef,
start => {adk_task_worker, start_link, [TaskRef]},
restart => temporary,
shutdown => 5000,
type => worker,
modules => [adk_task_worker]},
case supervisor:start_child(?SERVER, ChildSpec) of
{ok, Pid} -> complete_handoff(Pid, TaskRef, Work, Opts, {ok, Pid});
{ok, Pid, Info} ->
complete_handoff(Pid, TaskRef, Work, Opts, {ok, Pid, Info});
Error -> Error
end.
complete_handoff(Pid, TaskRef, Work, Opts, Started) ->
case adk_task_worker:handoff(Pid, TaskRef, Work, Opts) of
ok -> Started;
{error, Reason} ->
_ = supervisor:terminate_child(?SERVER, TaskRef),
_ = supervisor:delete_child(?SERVER, TaskRef),
{error, Reason}
end.
init([]) ->
{ok, {#{strategy => one_for_one,
intensity => 20,
period => 10}, []}}.