在 Elixir 中异步运行长时间运行的任务

Jas*_* O. 2 asynchronous task elixir

我有一个以 csv 格式保存数据的模块,这需要相对较长的时间,具体取决于数据大小。Elixir 异步完成此操作的方法是什么?我尝试使用代理,但进程超时。

在此处输入图片说明

defmodule FinReporting.Export_CSV do
    alias FinReporting.DistributeRepo
    alias FinReporting.InterfaceMdl
    import Ecto.Query

    def start_link do
        Agent.start_link(fn -> HashDict.new end, name: __MODULE__)
    end

    def export do
        Agent.update(__MODULE__, fn dict -> 

                                    export_sub()    
                                end)
    end

    defp export_sub do
        file = File.open!("test.csv",[:write, :utf8])
        IO.puts("===> CSV export of NGInterface file started.")
        DistributeRepo.all(from entry in InterfaceMdl, limit: 100000, select: %{ field1: entry.field1, amount: entry.amount})
                |>Enum.map(fn(entry)-> %{entry|amount: Decimal.to_string(entry.amount)}end) 
                |> Enum.map(fn(m) -> [m.field1, m.amount] end) 
                |> CSV.encode 
                |> Enum.each(&IO.write(file, &1))

        IO.puts("===> CSV export of NGInterface file completed.")
        _ = File.close(file) 
    end
end
Run Code Online (Sandbox Code Playgroud)

Dog*_*ert 5

您可以使用第三个参数指定自定义超时Agent.update。您可以传递一个整数来指定毫秒数,例如60000一分钟或:infinity无限超时。

Agent.update(__MODULE__, fn dict -> export_sub() end, 60000)
Run Code Online (Sandbox Code Playgroud)

但, Agent.update等待函数完成执行,这不是您想要的。

你想要Task,特别是Task.async/1.

Task.async(fn -> export_sub() end)
Run Code Online (Sandbox Code Playgroud)

这将返回一个Task结构体,您可以稍后在应用程序中使用该结构体等待Task.await或使用Task.yield. 所有这些以及更多内容都在Task 的文档中进行了详细解释。