可观察的更改订户出错

时间:2017-05-15 05:21:03

标签: 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_MESSAGE_ID));
        })
        .doOnComplete(this::saveCutOffTime)
        .doOnError(e -> informUserImpactedHostnames(hostnames, 
            theRestOfHostnamesInside(credsXmlStream, e))) // I don't think this is right
        .onErrorResumeNext(Flowable.empty())
        .count();

我想发送受故障影响的所有主机名。但是,请参阅上面的评论。我不认为这是正确的,因为流被消耗了两次。例如,如果theRestOfHostnamesInside的实施是credsStream.map(c -> c.getHostname()), e)

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

2 个答案:

答案 0 :(得分:0)

onErrorResumeNext应该用于提供您想要回退的流量。

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

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

其他方法是将已经处理过的密钥存储在一个集合中,并在onErrorResumeNext中过滤掉这些密钥,但是您必须确保所述集合特定于下面的每个subscribecount() ......所以不那么容易。

答案 1 :(得分:0)

你可以在flatMap内部做到这一点

        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.just(x)我只是把它们放在那里作为例子。