如果已经锁定了Couchbase getAndLock的延迟重试的正确方法?

时间:2015-04-02 08:33:29

标签: java couchbase reactive-programming rx-java

我正在使用新的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阻碍了吗?

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)。