订阅长时间运行的异步查询

时间:2018-07-17 13:39:13

标签: spring-data couchbase project-reactor spring-data-couchbase couchbase-java-api

我正在尝试以反应方式从Couchbase提取大型数据集。 我使用spring数据提供的ReactiveCouchbaseRepository

public interface ReactiveFooRepository extends ReactiveCouchbaseRepository<Foo, String> {

    @Query("#{#n1ql.selectEntity} WHERE ... ORDER BY ...")
    Flux<Foo> findAll();
}

在我的服务中,我按以下方式订阅

repository.findAll()
          .subscribe(this::process,
                     t -> LOGGER.error("Failed to process.", t));

在我的测试数据集上,这很好用,但是在生产中,该查询返回了一个大型数据集,并运行了大约20-25秒。

我的理解是,这正是反应式存储库的确切含义:无需进行显式分页等即可消耗大量结果。

但是我得到的是IllegalStateException

Failed to process.
java.lang.IllegalStateException: The content of this Observable (queryRow.13de03e2-9271-47e2-9d56-df01038011f9) is already released. Subscribe earlier or tune the CouchbaseEnvironment#autoreleaseAfter() setting.
...

提高autoreleaseAfter超时时间似乎不是一个可靠的解决方案。 似乎在发布第一个结果元素之前,将整个结果缓冲在Couchbase中。

我弄错了吗?关于可能的问题或解决方案有什么想法?

编辑

我发现的一个问题是订购。我认为Couchbase必须先获取整个结果集才能对其进行排序。 删除ORDER BY子句后,我可以流式传输结果,但只能在直接使用Java SDK时进行。

以下代码可以正常工作,并立即开始流式传输数据:

public void applyToAllFooAsync(Consumer<Optional<Foo>> consumer) {
    String queryString = String.format("SELECT meta().id, _class, field1, field2, ... "
                                           + "FROM %s "
                                           + "WHERE ... ",
                                       getQuotedBucketName());

    N1qlParams params = N1qlParams.build().consistency(ScanConsistency.STATEMENT_PLUS).pretty(false);
    N1qlQuery query = N1qlQuery.simple(queryString, params);

    asyncBucket
        .query(query)
        .flatMap(AsyncN1qlQueryResult::rows)
        .map(this::getFoo)
        .forEach(consumer::accept);
}

protected Optional<Foo> getFoo(AsyncN1qlQueryRow row) {
    try {
        return Optional.of(objectMapper.readValue(row.byteValue(), clazz));
    } catch (IOException e) {
        LOGGER.warn("Could not map Foo to object.", e);
        return Optional.empty();
    }
}

applyToAllOperationsAsync(System.out::println));

但是,如果我在ReactiveCouchbaseRepository中使用完全相同的查询,则需要花费几秒钟的时间,然后抛出上面显示的异常。

有人知道可能源自不同的行为吗? 有人可以指出我在Spring数据代码中使用实际Java SDK的类或方法吗?

0 个答案:

没有答案