Kotlin Coroutines-无限流可以批量分发

时间:2019-07-16 20:29:36

标签: kotlin kotlin-coroutines

我正在寻求实现用于处理无限消息流的管道。我是协程新手,并试图跟着文档一起学习,但我不确定自己在做正确的事情。

我的无限数据流包含成批记录,我想将每个记录的处理散发出给协程,等待一批完成(记录统计信息和资料),然后继续下一批。

                    -> process [record] \   
source -> [records] -> process [record]  -> [log batch stats]
                    -> process [record] /   

         |------------------- while(true) -------------------|

我计划的是有2个Channel,一个用于无限流,一个用于中间记录,这些记录将在每批中填充并清空。

runBlocking {
  val infinite: Channel<List<Record>> = produce { send(source.getBatch()) }
  val records = Channel<Record>(Channel.Factory.UNLIMITED)

  while(true) {
    infinite.receive().forEach { records.send(it) }
    while(!records.isEmpty()) {
      launch { process(records.receive()) }
    }

    // ??? Wait for jobs?

    logBatchStats()
  }

}

通过谷歌搜索,似乎不鼓励等待工作,再加上我不确定是否在频道上调用.map会收到消息,将其转换为工作:

records.map { record -> launch { process(record) } }

产生Channel<Job>。看来我可以调用.toList()将其折叠起来,但是那我需要参加工作吗?再次,谷歌建议通过做父母的工作来做到这一点,但我不确定如何使用launch来做到这一点。

无论如何,对此非常重要。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

我看不到拥有两个频道的理由。您可以直接遍历记录列表。并且您应该使用async而不是launch。然后,您可以使用await甚至更好的awaitAll作为结果列表。

val infinite: ReceiveChannel<List<Record>> = produce { ... }

while(true) {
    val resultsDeferred = infinite.receive().map {
        async {
            process(it)
        }
    }

    val results = resultsDeferred.awaitAll()

    logBatchStats()
}