如何使用RxJava 2来重新编排比赛?

时间:2017-06-22 13:35:27

标签: java rx-java reactive-programming rx-java2

假设我们有一组片状(有时是失败的)解析器,它们可能或者可能不能处理给定的文件,即给定的解析器成功概率为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解决吗?

1 个答案:

答案 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 */);

应符合您的要求。