我正在将CSV导入数据库,我解析它并处理每个条目:
stream= File.stream!(path)
|> CSVParser.parse_stream
|> Stream.map(fn row ->
case row do
[_] -> nil
_ -> row
end
end)
|> Stream.chunk(chunck_n, step, [])
|> Task.async_stream(CsvsController, :chunk_handler_fn, [process_name, db_map, entity_name, entity_id, entity_ios2, table_name, invite?, background_job_id], max_concurrency: 10)
Task.start_link(Stream, :run, [stream])
会有数百个块,通过CsvsController
处理但是如何捕获会阻止当前进程的错误?因为Task.start_link
与当前流程相关联。
答案 0 :(得分:0)
将Task
链接到您的流程后,此流程将收到带有签名:DOWN
的{{1}}信息消息。假设此代码在{:DOWN, _, :process, _pid, _reason}
内,您可能只是实现处理程序:
GenServer
在那里做任何你想做的事。
def handle_info({:DOWN, _, :process, _pid, _reason}, state) do
...
end
处理此问题的示例(不完整,但您明白了):GenServer
现在您要将它放入监督树中,并在需要时拨打defmodule CsvImporter do
use GenServer
def start_link(_opts \\ []) do
GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
end
def process!(path), do: GenServer.call(__MODULE__, {:process, path})
def handle_call({:process, path}, _from, state) do
stream = path
|> File.stream!()
|> CSVParser.parse_stream()
.....
{:ok, pid} = Task.start_link(Stream, :run, [stream])
{:reply, pid, state}
end
def handle_info({:DOWN, _, :process, _pid, reason}, state) do
# check **reason** for whether it was finished
# unexpectedly and do something
end
end
。
我越想到这一点,我就越相信你实际上根本不需要任务。只需CsvImporter.process!(path)
到此cast
,GenServer
本身(GenServer
s的处理就是异步),您就已经完成了设置。