Elixir long 运行 后台任务未完成,有时会崩溃
Elixir long running background task doesn't complete, sometimes crashes
作为一点背景知识,我有一个端点负责视频上传。我想要做的是将视频文件从请求复制到一个临时位置,并启动一个异步任务(ffmpeg shell 进程)以在后台对该视频进行转码,以便我的端点可以 return 一个 200 及时,并且响应不等待 ffmpeg 完成该视频的转码。
这是来自控制器的代码。
def create(conn, %{"file" => file ... })
uuid = Video.uuid()
tmp_path = Application.get_env(:myapp, :video_tmp_path) <> "/" <> uuid
:ok = File.cp(file.path, tmp_path)
VideoService.process(tmp_path, final_path)
VideoService 的内部如下所示。
defmodule MyApp.Services do
defmodule VideoService do
def process(tmp_path, final_path) do
Task.start_link fn ->
System.cmd("ffmpeg", ["-i", tmp_path, final_path, "-hide_banner"])
File.rm(tmp_path)
end
end
end
end
我在这里遇到的问题是,无论如何,System.cmd("ffmpeg")
调用之后的任何内容都不会在 VideoService
中执行,有时 System.cmd
调用甚至不会启动一个 ffmpeg
过程。我在这里做错了什么吗?我需要的是一种从控制器/服务在后台旋转此 ffmpeg
shell 进程并在视频上传时响应 200 的方法。提前感谢您的帮助。我是 elixir / OTP 的新手,所以我确定我在做一些愚蠢的事情。
我也随机看到如下错误
erl_child_setup: failed with error 32 on line 240
感谢mudasobwa 和Dogbert 的帮助来回答这个问题。我跟着 this guide 找到了一个独立的主管,并像他们建议的那样 运行 在我的 phoenix stack 中加入。这样做的要点是在 lib/myapp.ex
中添加一行,创建一个这样的主管
supervisor(Task.Supervisor, [[name: MyApp.TaskSupervisor]])
然后当你想 运行 以那个主管为父的任务时,你可以 运行
Task.Supervisor.start_child(MyApp.TaskSupervisor, fn -> do_stuff() end)
在我的案例中,do_stuff 涉及生成一个 ffmpeg 进程并进行一些文件清理。这里的基本思想是,您正在以 Supervisor 作为父级进行这项工作,这样即使请求退出并且该进程终止,您的 supervisor 仍然活着并且很好,因为当您的应用程序启动时它始终处于运行状态。
作为一点背景知识,我有一个端点负责视频上传。我想要做的是将视频文件从请求复制到一个临时位置,并启动一个异步任务(ffmpeg shell 进程)以在后台对该视频进行转码,以便我的端点可以 return 一个 200 及时,并且响应不等待 ffmpeg 完成该视频的转码。
这是来自控制器的代码。
def create(conn, %{"file" => file ... })
uuid = Video.uuid()
tmp_path = Application.get_env(:myapp, :video_tmp_path) <> "/" <> uuid
:ok = File.cp(file.path, tmp_path)
VideoService.process(tmp_path, final_path)
VideoService 的内部如下所示。
defmodule MyApp.Services do
defmodule VideoService do
def process(tmp_path, final_path) do
Task.start_link fn ->
System.cmd("ffmpeg", ["-i", tmp_path, final_path, "-hide_banner"])
File.rm(tmp_path)
end
end
end
end
我在这里遇到的问题是,无论如何,System.cmd("ffmpeg")
调用之后的任何内容都不会在 VideoService
中执行,有时 System.cmd
调用甚至不会启动一个 ffmpeg
过程。我在这里做错了什么吗?我需要的是一种从控制器/服务在后台旋转此 ffmpeg
shell 进程并在视频上传时响应 200 的方法。提前感谢您的帮助。我是 elixir / OTP 的新手,所以我确定我在做一些愚蠢的事情。
我也随机看到如下错误
erl_child_setup: failed with error 32 on line 240
感谢mudasobwa 和Dogbert 的帮助来回答这个问题。我跟着 this guide 找到了一个独立的主管,并像他们建议的那样 运行 在我的 phoenix stack 中加入。这样做的要点是在 lib/myapp.ex
中添加一行,创建一个这样的主管
supervisor(Task.Supervisor, [[name: MyApp.TaskSupervisor]])
然后当你想 运行 以那个主管为父的任务时,你可以 运行
Task.Supervisor.start_child(MyApp.TaskSupervisor, fn -> do_stuff() end)
在我的案例中,do_stuff 涉及生成一个 ffmpeg 进程并进行一些文件清理。这里的基本思想是,您正在以 Supervisor 作为父级进行这项工作,这样即使请求退出并且该进程终止,您的 supervisor 仍然活着并且很好,因为当您的应用程序启动时它始终处于运行状态。