如何使用elixir流批量处理事件

时间:2018-01-10 12:09:39

标签: elixir

我有一个csv_file a。)首先,每行需要转换为xml和 b。)第二,转换后的xml将被发送到rails端进行一些数据库写操作。

以下是我的 Flow 代码。

flow = csv_rows
 |> Flow.from_enumerable()
 |> Flow.partition
 |> Flow.map(&(CSV.generate_xml(&1)))
 |> Flow.map(&(CSV.save_to_rails_databse(&1)))
 |> Flow.run

对于小型csv文件,Everyting工作正常,但是当csv_file非常大(假设为20,000)记录时,执行第二次操作(即在rails侧写入数据库)试图在同一时间插入两个很多记录时间,因为elixir同时向rails侧发送了太多请求,因此数据库达到了峰值限制。

处理50个批次中的事件是否合适,min_demandmax_demand在这种情况下是否有用。

1 个答案:

答案 0 :(得分:10)

您可以使用Flow.map_state/2接收特定州的整个州(在您的情况下,由于您正在映射,州将是该批次中的事件)。

你会想在这里使用三个参数,全部给予from_enumerable:

  • min_demand:这实际上是批量大小
  • max_demand:阶段之间流动的最大行数
  • 阶段:处理数据的并发阶段数。在您的情况下,同时处理多少批次

其他一些注意事项:

  • 您不需要分区,因为您没有进行任何分组
  • 考虑使用允许CSV作为流使用的NimbleCSV - 如果CSV太大,这有助于内存使用
  • 在这个示例中,您可能根本不需要Flow,Task.asycn_stream/3就足够了

当我们研究Flow时,我们能够获得一些Flow课程并将其应用回Elixir。其中一个课程产生了WITH RECURSIVE recursetree(name, parent) AS ( SELECT name, parent FROM data_indicators UNION ALL SELECT t.name, t.parent FROM data_indicators t, recursetree rt WHERE rt.name = t.parent ); SELECT * FROM recursetree` }, (err, res) => { .... ,当您想要在没有缩小阶段的集合上进行映射时,这非常有用,这正是您所拥有的:

Task.async_stream/3

我还没有对代码进行过测试,但它应该提供足够的指导。它应该与Flow一样快但没有额外的依赖。