Mam zadanie Elixir, które zajmuje trochę czasu (10 sekund). Gdy aplikacja jest uaktualnieniem, zadanie to zostanie zabity przez Task.Supervisor
mimo na shutdown: 30000
:Zadanie z eliksirem - Zgrabne zamknięcie
=SUPERVISOR REPORT==== 13-Aug-2015::00:03:09 ===
Supervisor: {local,tasks_sup}
Context: child_terminated
Reason: killed
Offender: [{pid,<0.304.0>},
{id,'Elixir.Task.Supervised'},
{mfargs,{'Elixir.Task.Supervised',start_link,undefined}},
{restart_type,temporary},
{shutdown,30000},
{child_type,worker}]
Nie wiem, jak wdzięcznie zatrzymać zadanie (czekać aż zadanie jest zakończone) w sprawie uaktualnienia aplikacji. Oto kod opisujący mój problem:
defmodule MyApp do
use Application
def start(_, _) do
MyApp.Supervisor.start_link([])
end
end
defmodule MyApp.Supervisor do
use Supervisor
def start_link(state) do
Supervisor.start_link(__MODULE__, state, name: __MODULE__)
end
def init(state) do
children = [
supervisor(Task.Supervisor, [[name: :tasks_sup, shutdown: 30000]]),
worker(MyApp.Worker, [state], restart: :permanent)
]
supervise(children, strategy: :one_for_one)
end
end
defmodule MyApp.Worker do
def start_link(state) do
GenServer.start_link(__MODULE__, state, [name: MyApp.Worker])
end
def init(state) do
{:ok, state}
end
def handle_call(:which_children, _, state) do
children = [{Task.Supervisor, :tasks_sup, :supervisor, [Task.Supervisor]}]
{:reply, children, state}
end
def handle_info({:task, data}, state) do
Task.Supervisor.async(:tasks_sup, MyApp.TaskRunner, :perform, [data])
end
def handle_info(_, state) do
{:noreply, state}
end
end
defmodule MyApp.TaskRunner do
def perform(data) do
# some 10 secs job
end
end
Czy istnieją jakieś myśli lub założenia jak czekać aż MyApp.TaskRunner.perform
wykończeń, a następnie pozwolić, aby zatrzymać zadanie?
Nie ma dla mnie znaczenia, jak przetwarzać zadania: korzystanie z natywnego Elixir's Task
lub przez własny moduł TaskProcessor.
Task.Supervisor.async
łączy zadania z dzwoniącym, co może być problemem. Jednak próbowałem kilka razy różnych przypadków z async
i start_link
i za każdym razem otrzymałem taki sam wynik. Moja ostatnia próba była:
children = [
supervisor(Task.Supervisor, [[name: :tasks_sup, shutdown: 30000]]),
worker(MyApp.Worker, [state], restart: :permanent)
]
supervise(children, strategy: :one_for_one)
i
Task.Supervisor.start_child(:tasks_sup, MyApp.TaskRunner, :perform, [data])
Pracownik zginął po około 2-3 sekund.