我正在使用新的Couchbase Java Client API 2.1.1,因此使用JavaRx来访问我的Couchbase群集。
在已锁定的文档上使用异步getAndLock
时,getAndLock失败并显示TemporaryLockFailureException
。在另一个SO问题(rxjava: Can I use retry() but with delay?)中,我发现了如何以延迟重试。
这是我采用的代码:
CountDownLatchWithResultData<JsonDocument> resultCdl = new CountDownLatchWithResultData<>(1);
couchbaseBucket.async().getAndLock(key, LOCK_TIME).retryWhen((errorObserver) -> {
return errorObserver.flatMap((Throwable t) -> {
if (t instanceof TemporaryLockFailureException) {
return Observable.timer(RETRY_DELAY_MS, TimeUnit.MILLISECONDS);
}
return Observable.error(t);
});
}).subscribe(new Subscriber<JsonDocument>() {
@Override
public void onCompleted() {
resultCdl.countDown();
}
@Override
public void onError(Throwable e) {
resultCdl.countDown();
}
@Override
public void onNext(JsonDocument t) {
resultCdl.setInformation(t);
}
});
........
resultCdl.await();
if (resultCdl.getInformation() == null) {
//do stuff
} else ....
(CountDownLatchWithResultData
只是扩展了一个普通的CountDownLatch
,并在计数达到0之前添加了两个方法来存储一些信息并在之后检索它。
所以基本上我喜欢这段代码
RETRY_DELAY_MS
发生TemporaryLockFailureException
,则每隔onNext
毫秒尝试无限次锁定,然后调用onNext
resultCdl.getInformation()
现在的问题是,在重试时,它只会重试一次,而onNext
中的JsonDocument在这种情况下始终为null,即使文档存在也是如此。似乎永远不会调用Observable.timer
如果没有例外,代码工作正常
显然我在这里做错了,但我不知道问题可能在哪里。返回retryWhen
是否意味着使用此新Obervable还会再次执行先前关联的CountDownLatch
?它是{{1}}计数1阻碍了吗?
答案 0 :(得分:0)
这个很微妙。最高版本2.2.0,SDK中的Observable
位于&#34; hot&#34;类别。实际上,这意味着即使没有订阅,它们也会开始发布。它们还会向每个新的Subscriber
发出相同的数据,因此实际上它们会缓存数据。
所以你重试的是重新订阅Observable
,它总会发出同样的东西(在这种情况下是一个错误)。我怀疑它只是因为锁定最大持续时间为LOCK_TIME
...
尝试将asyncBucket.getAndLock
中的Observable.defer
电话包裹起来(或迁移到2.2.x SDK,如果你可以做的话,请参阅release and migration notes starting from 2.2.0)。