我正在寻求实现用于处理无限消息流的管道。我是协程新手,并试图跟着文档一起学习,但我不确定自己在做正确的事情。
我的无限数据流包含成批记录,我想将每个记录的处理散发出给协程,等待一批完成(记录统计信息和资料),然后继续下一批。
-> 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
来做到这一点。
无论如何,对此非常重要。
感谢您的帮助。
答案 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()
}