I’d additionally recommend using a Task.Supervisor.
iex(1)> Supervisor.start_link([{Task.Supervisor, name: MyTaskSupervisor}], strategy: :one_for_one)
{:ok, #PID<0.114.0>}
iex(2)> Task.Supervisor.async_nolink(MyTaskSupervisor, fn -> :awesome_task end)
%Task{
mfa: {:erlang, :apply, 2},
owner: #PID<0.112.0>,
pid: #PID<0.117.0>,
ref: #Reference<0.987707504.2573795360.120005>
}
iex(3)> flush()
{#Reference<0.987707504.2573795360.120005>, :awesome_task},
{:DOWN, #Reference<0.987707504.2573795360.120005>, :process, #PID<0.117.0>, :normal}
iex(4)> Task.Supervisor.async_nolink(MyTaskSupervisor, fn -> raise "uh oh" end)
%Task{
mfa: {:erlang, :apply, 2},
owner: #PID<0.112.0>,
pid: #PID<0.120.0>,
ref: #Reference<0.987707504.2573795360.120046>
}
iex(5)> flush()
{:DOWN, #Reference<0.987707504.2573795360.120178>, :process, #PID<0.129.0>,
{%RuntimeError{message: "uh oh"}, ...}}
Docs for async_nolink/3 have some more information on this. Basically, if the task succeeds, you’ll receive a {task_ref, result} message. Regardless of success of failure, you’ll receive a {:DOWN, ref, :process, pid, reason} message. If it was a normal exit, that reason will be :normal. Otherwise, it was abnormal.
Your process kicking off these tasks can implement handle_info and pattern-match on these to broadcast the appropriate PubSub message.






















