如何在出错时更改订阅者?我有一个来自数据库的冷流消耗。请参阅以下案例:
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]的行)。
答案 0 :(得分:0)
onErrorResumeNext
应该用于提供您想要回退的流量。
然而,主要的困难是避免重复。如果你说的源是冷的,你将重新做一个DB请求,如果最初订阅的序列在错误之前发出了一些数据,那么将重新发出相同的数据。
您可以在distinct
之后链接onErrorResumeNext
来缓解这种情况(您应该能够提供keySelector
来指示如何检测重复项)。但是你必须确保使用一个标准,该标准不会将源中的两个元素标记为重复(以便仅消除重试创建的重复项)。
其他方法是将已经处理过的密钥存储在一个集合中,并在onErrorResumeNext
中过滤掉这些密钥,但是您必须确保所述集合特定于下面的每个subscribe
。 count()
......所以不那么容易。
答案 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)
我只是把它们放在那里作为例子。