我有一个以csv格式保存数据的模块,这需要相对较长的时间,具体取决于数据大小。 Elixir异步完成此任务的方法是什么?我尝试使用Agent,但过程超时。
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
答案 0 :(得分:4)
您可以使用Agent.update
的第三个参数指定自定义超时。您可以传递一个指定毫秒数的整数,例如60000
一分钟,或:infinity
无限超时。
Agent.update(__MODULE__, fn dict -> export_sub() end, 60000)
但是,Agent.update
等待函数完成执行,这不是你想要的。
您想要Task
,特别是Task.async/1
。
Task.async(fn -> export_sub() end)
这将返回Task
结构,您可以使用Task.await
稍后在应用程序中等待,或使用Task.yield
询问其状态。 the documentation of Task中详细解释了所有这些以及更多内容。