alP*_*ino 6 shutdown task elixir
我有Elixir Task,需要一些时间(10秒).当应用程序升级时,Task.Supervisor
尽管有以下情况,此任务仍被终止shutdown: 30000
:
=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}]
Run Code Online (Sandbox Code Playgroud)
在应用程序升级时,我不知道如何优雅地停止任务(等到任务完成).这是描述我的问题的代码:
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
Run Code Online (Sandbox Code Playgroud)
是否有任何想法或假设如何等到MyApp.TaskRunner.perform
完成然后允许停止任务?
对我来说如何处理任务并不重要:使用本机Elixir Task
或通过自己的一些TaskProcessor模块.
Task.Supervisor.async
将任务链接到调用者,这可能是一个问题.不过,我试了几次不同的情况下,与async
和start_link
每一次得到了相同的结果.我的最新测试是:
children = [
supervisor(Task.Supervisor, [[name: :tasks_sup, shutdown: 30000]]),
worker(MyApp.Worker, [state], restart: :permanent)
]
supervise(children, strategy: :one_for_one)
Run Code Online (Sandbox Code Playgroud)
和
Task.Supervisor.start_child(:tasks_sup, MyApp.TaskRunner, :perform, [data])
Run Code Online (Sandbox Code Playgroud)
工人在大约2-3秒后被杀死.
这些链接可能会导致您的任务失败。因为工作人员调用Task.Supervisor.async
,它会将任务链接到您的工作人员。Worker 的超时时间为 5000 毫秒,因此它将在 Supervisor 之前关闭,从而杀死任务。您可以通过设置早期报告来确认这一点。
顺便说一句,只有async
当您稍后通过同一进程调用时才应该调用await
,但这里的情况似乎并非如此。您可能应该Task.Supervisor.start_child
改为调用(因此任务不会链接到调用者)。
您的函数被杀死的另一个可能原因是虚拟机仅保留最新的两个代码模块版本。如果您在短时间内升级两次,旧版本将被清除,并且其正在运行的进程将被终止。