2017-08-06 128 views
1

我有一個模塊可以將數據保存爲csv格式,這取決於數據大小需要相對較長的時間。 Elixir如何異步完成此任務?我嘗試使用代理,但過程超時。在Elixir中異步運行長時間運行的任務

enter image description here

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 

回答

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中有詳細的解釋。