Rx java 错误时可观察到的变化

Rx java 错误时可观察到的变化,rx-java,rx-java2,project-reactor,Rx Java,Rx Java2,Project Reactor,错误时如何更改订阅服务器?我有一个冷流从数据库消费。请参见以下案例: return coctailBundleStream .doOnNext(c -> { hostnames.add(c.get(KEY_HOSTNAME)); // [A] sendToOutboundQueue(c.get(KEY_CREDS)); archiveSentMessage(c.get(KEY_CREDS), c.get(KEY_

错误时如何更改订阅服务器?我有一个冷流从数据库消费。请参见以下案例:

return coctailBundleStream
        .doOnNext(c -> {
          hostnames.add(c.get(KEY_HOSTNAME)); // [A]

          sendToOutboundQueue(c.get(KEY_CREDS));
          archiveSentMessage(c.get(KEY_CREDS), c.get(KEY_MESSAGE_ID));
        })
        .doOnComplete(this::saveCutOffTime)
        .doOnError(e -> informUserImpactedHostnames(hostnames, 
            theRestOfHostnamesInside(credsXmlStream, e))) // I don't think this is right
        .onErrorResumeNext(Flowable.empty())
        .count();
我想发送受故障影响的所有主机名。但是,请看我上面的评论。我认为这是不对的,因为这条流被消耗了两次。例如,如果
theRestOfHostnamesInside
的实现是
credstream.map(c->c.getHostname()),e)


我认为,理想情况下,错误处理程序应该使用另一个订阅继续流,该订阅将其余主机名提取到一个列表中,然后将该列表与前一个列表一起附加(请参见标有[a]的行)。

onErrorResumeNext
应该用于提供您想要回退的可流动主机名

然而,主要的困难是避免重复。如果源代码如您所说是冷的,那么您将重新执行一个DB请求,并且如果最初订阅的序列在出错之前发出了一些数据,那么相同的数据将重新发出

您可以通过在
onErrorResumeNext
之后链接
distinct
来缓解这种情况(您应该能够提供
键选择器来指示如何检测重复项)。但您必须确保使用的条件不会将源中的两个元素标记为重复项(以便仅消除重试创建的重复项)


另一种方法是将自己已经处理过的密钥存储在一个集合中,并在
onErrorResumeNext
中过滤掉这些密钥,但您必须确保所述集合特定于
subscribe
count()下游生成的每个
subscribe
。。。所以没那么容易。

onErrorResumeNext
应该用于提供您想要回退的可流动性

然而,主要的困难是避免重复。如果源代码如您所说是冷的,那么您将重新执行一个DB请求,并且如果最初订阅的序列在出错之前发出了一些数据,那么相同的数据将重新发出

您可以通过在
onErrorResumeNext
之后链接
distinct
来缓解这种情况(您应该能够提供
键选择器来指示如何检测重复项)。但您必须确保使用的条件不会将源中的两个元素标记为重复项(以便仅消除重试创建的重复项)


另一种方法是将自己已经处理过的密钥存储在一个集合中,并在
onErrorResumeNext
中过滤掉这些密钥,但您必须确保所述集合特定于
subscribe
count()下游生成的每个
subscribe
。。。所以没那么容易。

你可以在平面地图内完成

        Observable.fromIterable(yourList)
            .flatMap(x ->{
                Observable.just(x)
                        .map(data -> yourNormalSave(data))
                        .onErrorReturn(errorResult)
            })
            .subscribe(result ->{
                        if(result != errorResult)
                            count++;
                        eles{
                        //error received here
                        }  
            }
            );

所以在flatMap内部,如果您遇到错误,它会将其更改为正常类型,但下游对此一无所知。因此,您的下游用户也在onNext中使用它们。你可以正确地做它,而不是
x->Observable。只是(x)
我只是把它们作为一个例子放在那里。

你可以在平面图中做它

        Observable.fromIterable(yourList)
            .flatMap(x ->{
                Observable.just(x)
                        .map(data -> yourNormalSave(data))
                        .onErrorReturn(errorResult)
            })
            .subscribe(result ->{
                        if(result != errorResult)
                            count++;
                        eles{
                        //error received here
                        }  
            }
            );

所以在flatMap内部,如果您遇到错误,它会将其更改为正常类型,但下游对此一无所知。因此,您的下游用户也在onNext中使用它们。您可以正确地执行它,而不是
x->Observable。只是(x)
我只是把它们作为一个示例。

我不喜欢重新执行相同的DB请求。这对我来说似乎效率不高。这取决于最初的错误是什么,但你可以回退到第二个序列,只查询丢失的键。。。由于
onErrorResumeNext
将错误序列(如果有)中的数据与回退序列中的数据连接起来,这符合要求。我不喜欢重新执行相同的DB请求。这对我来说似乎效率不高。这取决于最初的错误是什么,但你可以回退到第二个序列,只查询丢失的键。。。由于
onErrorResumeNext
将错误序列(如果有)中的数据与回退序列中的数据连接起来,因此这符合要求