Ho un compito di elisir, che richiede un po 'di tempo (10 secondi). Quando l'applicazione è l'aggiornamento, questo compito viene ucciso da Task.Supervisor
nonostante il shutdown: 30000
:Task Elixir - Arresto agevole
=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}]
Non so come fermare con garbo il compito (attendere compito è completo) durante l'aggiornamento dell'applicazione. Qui è il codice che descrive il mio problema:
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
C'è qualche pensiero o ipotesi come aspettare fino MyApp.TaskRunner.perform
finiture e quindi consentire di fermare l'operazione?
Non ha importanza per me come elaborare le attività: utilizzando l'Elixir originale Task
o tramite il proprio modulo TaskProcessor.
Task.Supervisor.async
collega le attività al chiamante, che potrebbe essere un problema. Tuttavia, ho provato più volte casi diversi con async
e start_link
e ogni volta ho ottenuto lo stesso risultato. La mia ultima prova era:
children = [
supervisor(Task.Supervisor, [[name: :tasks_sup, shutdown: 30000]]),
worker(MyApp.Worker, [state], restart: :permanent)
]
supervise(children, strategy: :one_for_one)
e
Task.Supervisor.start_child(:tasks_sup, MyApp.TaskRunner, :perform, [data])
L'operaio è stato ucciso dopo circa 2-3 secondi.