检查是否有任何订户在RxJava中引发异常

时间:2016-08-18 08:07:51

标签: java rx-java reactivex

我正在尝试制作一个反应式RabbitMQ侦听器,它允许我们处理具有多个订阅者的每条消息。当所有订阅者成功完成时,我们只希望ack消息。

这是我目前的设置:

Observable
    .fromCallable(() -> {
        // Set up connection
        return consumer;
    })
    .flatMap(consumer -> Observable
        .fromCallable(consumer::nextDelivery)
        .doOnError(throwable -> {
            try {
                consumer.getChannel().getConnection().close();
            } catch (IOException ignored) { }
        })
        .repeat())
    .retryWhen(observable -> observable.delay(3, TimeUnit.SECONDS))
    .publish()
    .refCount();

这将建立一次连接,与所有订阅者共享所有消息,并在3秒后重新连接,如果由于例如兔子变得无法使用。

我仍然需要做的是acknack消息。由于我们所有的消息处理程序都是幂等的,所以如果任何处理程序发生故障,我可以重新排队消息,以确保每个处理程序都能成功完成。

有没有办法判断任何订阅者是否失败?我目前正在考虑订阅这样的东西:

public void subscribe(Action1 action) {
    deliveries
        .flatMap(delivery -> Observable
            .just(delivery)
            .doOnNext(action)
            .doOnError(throwable -> {
                // nack
            })
            .doOnCompleted(() -> {
                // ack
            })
        )
        .subscribe();
}

但是在第一次失败或成功时,这显然是acknack。有没有办法merge特定邮件的所有订阅者,然后检查错误或完成?

我还尝试过使用AtomicInteger计算所有订阅者的数量,然后计算成功/失败次数,但很明显,只要有人在处理过程中订阅或取消订阅,就不会在不阻止整个处理步骤的情况下进行同步。 / p>

我也可以给每个订阅者Observable<Delivery>并让他们返回错误或完成,类似于retryWhen(作为一种回复频道),但我无法生成事先确定所需的可观察数量并将其合并。

有什么想法吗?谢谢你的阅读!

2 个答案:

答案 0 :(得分:1)

您可以使用 onErrorResumeNext 来控制从管道传播的异常并设置 nack ,然后将您的onComplete用作 ack

这是一个例子

Observable.just(null).map(Object::toString)
                     .doOnError(failure -> System.out.println("Error:" + failure.getCause()))
                     .retryWhen(errors -> errors.doOnNext(o -> count++)
                     .flatMap(t -> count > 3 ? Observable.error(t) : Observable.just(null).delay(100, TimeUnit.MILLISECONDS)),
                                                     Schedulers.newThread())
                     .onErrorResumeNext(t -> {
                                              System.out.println("Error after all retries:" + t.getCause());
                                              return Observable.just("I save the world!");
                                          })
                     .subscribe(s -> System.out.println(s));

答案 1 :(得分:1)

您想使用Observable.mergeDelayError,然后使用其中一种.onError*方法。

第一个只在所有可观察者完成/出错之后传播错误;第二个将允许您在处理完成后处理错误。

编辑:要获得计数,请计算成功次数:

Object message = ...;
List<Action1<?>> actions = ...;
Observable.from(actions)
 .map(action ->
    Observable.defer(() -> Observable.just(action.call(message))
    .ignoreEmements()
    .cast(Integer.class)
    .switchIfEmpty(1)
    .onErrorReturnResumeNext(e->Observable.empty())
 )
 .compose(Observable::merge)
 .count();

它有点复杂,可以更清楚:拨打电话,忽略错误,计算成功。