RxJava 2.0-在publish()中处理未捕获子服务器错误的Resources

RxJava 2.0-在publish()中处理未捕获子服务器错误的Resources,java,exception-handling,rx-java,rx-java2,Java,Exception Handling,Rx Java,Rx Java2,我对RxJava相当陌生,和其他许多人一样,我正在尝试了解异常处理。我在网上读了不少帖子(例如,这里的讨论),认为我已经了解了这些概念的基本概念 在上面提到的讨论中,其中一张海报说,当订阅服务器中抛出异常时,RxJava会执行以下操作: 实现通用处理以记录故障并停止向其发送事件 (任何种类的)并清理该认购人和承运人的任何资源 使用任何剩余订阅打开 这或多或少也是我看到的,我唯一有问题的是“清理任何资源”位。为了说明这一点,让我们假设以下示例: 我想创建一个可观察对象,它侦听异步事件源(例如JMS

我对RxJava相当陌生,和其他许多人一样,我正在尝试了解异常处理。我在网上读了不少帖子(例如,这里的讨论),认为我已经了解了这些概念的基本概念

在上面提到的讨论中,其中一张海报说,当订阅服务器中抛出异常时,RxJava会执行以下操作:

实现通用处理以记录故障并停止向其发送事件 (任何种类的)并清理该认购人和承运人的任何资源 使用任何剩余订阅打开

这或多或少也是我看到的,我唯一有问题的是“清理任何资源”位。为了说明这一点,让我们假设以下示例:

我想创建一个可观察对象,它侦听异步事件源(例如JMS队列)和每个接收到的消息上的onNext()。所以在(伪)代码中,我会做类似的事情:

Observable<String> observable = Observable.create( s -> {
  createConnectionToBroker();
  getConsumer().setMessageListener(message -> s.onNext(transform(message)));
  s.setDisposable(new Disposable() {
    public void dispose() {
      tearDownBrokerConnection();
    }
  });
});
Observable<String> observableToSubscribeTo = observable.publish().refCount();

Disposable d1 = observableToSubscribeTo.subscribe(s -> ...);
Disposable d2 = observableToSubscribeTo.subscribe(s -> ...);
Observable=Observable.create(s->{
createConnectionBroker();
getConsumer().setMessageListener(消息->s.onNext(转换(消息));
s、 SetDispossible(新的Dispossible(){
公共空间处置(){
断开断开的断开连接();
}
});
});
由于我希望为许多订阅者/观察者重用消息侦听器,因此我不直接在创建的可观察对象上订阅,而是使用publish().refCount()团队。类似于此:

Observable<String> observable = Observable.create( s -> {
  createConnectionToBroker();
  getConsumer().setMessageListener(message -> s.onNext(transform(message)));
  s.setDisposable(new Disposable() {
    public void dispose() {
      tearDownBrokerConnection();
    }
  });
});
Observable<String> observableToSubscribeTo = observable.publish().refCount();

Disposable d1 = observableToSubscribeTo.subscribe(s -> ...);
Disposable d2 = observableToSubscribeTo.subscribe(s -> ...);
Observable-Observable-subscribeto=Observable.publish().refCount();
一次性d1=可观察订阅订阅订阅(s->…);
一次性d2=可观察订阅订阅订阅(s->…);
这一切都按预期进行。代码仅在建立第一个订阅时连接到JMS,而在最后一个观察者是
dispose()
d时关闭到代理的连接

然而当订户在
onNext()
ed时抛出异常时,事情似乎变得一团糟。正如预期的那样,抛出的观测者被核化,并且每当发布新事件时,将不再通知它。我的问题是,当所有剩余订户都是
dispose()
d时,将不再通知维护到MessageBroker连接的可观察订户。在我看来,抛出异常的订户似乎处于某种僵尸状态。当涉及到事件分布时,它会被忽略,但它会以某种方式阻止根可观察对象在最后一个订户是
dispose()
d时得到通知

我知道RxJava希望观察者确保不会抛出异常,而是正确处理最终的异常。不幸的是,如果我想提供一个库,向调用者返回一个可观察的,我对我的订阅者没有任何控制权。这意味着,我永远无法保护我的图书馆免受愚蠢的观察家的攻击

所以,我问自己:我是不是错过了什么?当订阅服务器抛出时,是否真的没有机会正确清理?这是一个bug还是只是我不理解库


非常感谢您的任何见解

如果您能展示一些单元测试来演示问题(不需要JMS),那就太好了

另外,RXJava2中的onNext不应该抛出;如果它这样做了,那就是一个未定义的行为。如果您不信任您的消费者,您可以使用一个可观察的终端转换器,它可以执行
safeSubscribe
,而不是普通的
subscribe
,它增加了对下游不当行为的保护:

.compose(o -> v -> o.safeSubscribe(v))

.compose(新的ObservableTransformer(){
@覆盖公共可观测应用(最终可观测源){
返回新的可观察(){

@Override public void subscribebeactual(Observerhi@akarnokd,感谢您的关注!我刚刚编写了一个基本单元测试来演示该行为,只是为了了解我不再能够复制它了?!:-非常尴尬,我必须说:-(因此,我可以假设问题出在我的胶水代码中的某个地方。为浪费您的时间而道歉!!!并感谢您对safeSubscribe()的评论。因为作为一个库,您永远不能信任使用代码,我真的很想强化它。一个行为不端的订阅者不应该对其他行为良好的订阅者产生任何副作用。