假设我们有一组片状(有时是失败的)解析器,它们可能或者可能不能处理给定的文件,即给定的解析器成功概率为p > 0
,或者总是失败({{1} })。是否可以使用RxJava让这组解析器订阅传入文件流并“竞争”解析文件?
鉴于解析器最初可能失败但仍能够解析文件,因此必须让它们重试一些退避策略。鉴于没有解析器也可以处理给定文件,重试计数应该是上限。
使用p=0
实现指数退避相对容易实现,类似这样(source):
retryWhen
但是,建立平行竞赛是我无法弄清楚如何做的事情。似乎source.retryWhen(errors ->
errors.zipWith(Observable.range(1, 3), (n, i) -> i)
.flatMap(retryCount -> Observable.timer((long) Math.pow(5, retryCount), TimeUnit.SECONDS))
);
运算符就是我们想要的,但是将它应用于任意数量的流似乎需要使用amb
,这(我认为)会阻止竞争的目的。我无法在互联网上找到与此blockingIterable
用例相关的任何有用信息。
到目前为止,我的尝试类似于:
amb
Set<Parser> parserSet = new HashSet<>();
parserSet.add(new Parser(..., ..., ...));
// Add more parsers
int numParsers = parserSet.size();
Flowable<Parser> parsers = Flowable.fromIterable(parserSet).repeat();
fileSource
.flatMap(f -> parsers.take(numParsers)
.map(p -> p.parse(f))
.retryWhen(/* snippet from above */)
.onErrorReturn(/* some error value */)
).take(1)
介绍了Flowable
运算符,该运算符最近添加了.parallel()
(see this pr),其ParallelFailureHandling
方法,但我不能似乎让其中一个人返回之后停止重试。
这个问题可以用RxJava解决吗?
答案 0 :(得分:1)
合理假设你的解析器是同步的,比如
Set<Parser> parserSet = new HashSet<>();
parserSet.add(new Parser(..., ..., ...));
// Add more parsers
int numParsers = parserSet.size();
ArrayList<Flowable<T>> parserObservableList = new ArrayList<>();
for (Parser p: parserSet) {
parserObservableList.add(Flowable.fromCallable(() -> p.parse(f))
.retryWhen(/* Add your retry logic */)
.onErrorReturn(/* some error value */));
}
Flowable.amb(parserObservableList).subscribe(/* do what you want with the results */);
应符合您的要求。