我正在使用我们下载一组文件的应用程序,并在运行中处理所有这些文件。这就是我正在做的事情:
Observable.from(fileUrls)
.compose(downloadAndPersistFiles())
.compose(processPersistedData())
.subscribe()
fileUrls
是文件网址集。 downloadAndPersistFiles
从下载的文件中提取数据并将其保存到本地数据库中。每次成功下载并保留文件数据时,它都会返回一个事件。此外,我使用Schedulers.io()
来启动线程池以尽快下载这些文件。
private <T> Observable.Transformer<T, T> downloadAndPersistFiles() {
return observable -> observable
.flatMap(fileUrls -> Observable.from(fileUrls)
.subscribeOn(Schedulers.io())
.compose(download())
.compose(saveToDb());
}
对于每个成功下载和处理的文件,我运行一个额外的任务,这基本上是一组针对db的查询以提取其他数据。
private <T> Observable.Transformer<T, T> processPersistedData() {
return observable -> observable
//modified place - debounce, throttleFirst, throttleLast etc
.flatMap(file -> Observable.from(tasks)
.compose(runQueryToExtractData())
.toList()
.flatMap(ignored -> Observable.just(file)));
}
我知道它不能很好地扩展,数据库中的数据集会增长,因此查询会花费越来越多的时间。
从processPersistedData
(它使用一个线程池)的每个事件调用 downloadAndPersistFiles
,所以在某些时候,有几个processPersistedData
操作并行运行,我想要仅限于一个。
这是我到目前为止所尝试的内容:
debounce
超时 - 它在每个下载文件后增加了一个额外的延迟,如果下载文件比超时花费的时间少,那么流将会饿死,直到有足够大的文件下载和持久化
需要更长的时间throttleLast
- 每次下载文件后都会额外延迟,因为我需要等到时间窗口结束throttleFirst
- 第一个文件没有延迟,但我可能会错过最后一些事件 - 这是我到目前为止找到的最佳解决方案。我在这里遇到的主要问题是我无法同步下载文件和运行查询 - 一开始查询速度非常快,所以我希望尽可能使用短暂的超时,但随着时间的推移它们可能需要10-20秒,所以显然我想在这个时候放慢速度。此外,它不会阻止运行两个debounce with selector
- 听起来很完美!我可以使用processPersistedData
作为选择器,它会在processPersistedData
运行时去除所有事件并在完成后立即使用任何新事件但在我尝试之后processPersistedData
每次运行 - 为每个事件创建了新的流processPersistedData
。您是否有任何其他想法可以解决这个问题的方法?或者当我尝试debounce with selector
时,我是否想念?
答案 0 :(得分:0)
flatMap()
运算符采用一个额外的参数来约束并行操作的数量。
private <T> Observable.Transformer<T, T> processPersistedData() {
return observable -> observable
.flatMap(input -> Observable.from(tasks)
//modified place - debounce, throttleFirst, throttleLast etc
.compose(runQueryToExtractData())
.toList()
.flatMap(ignored -> Observable.just(input)), 1);
}
1
表示flatMap()
一次只处理一个项目。
顺便说一句,如果您有compose(runQueryToExtractData())
,则可能需要使用Completable
。