当前位置: 首页 > 知识库问答 >
问题:

spring数据couchbase,无法使用反应编程按id删除文档

彭胡媚
2023-03-14

最近我们决定在我们的项目中使用spring-WebFlux和couchbase,并且我们需要帮助如何在反应编程中解决下面的用例

>

  • 验证请求并将其保存在Bucket1 couchbase中(我们使用了javax.validation和spring的ReactiveCouchBaseRepository。
  • 调用外部服务(我们使用webclient调用API。

    >

  • 成功后,

    • 将审核文档写入bucket2。
    • 获取插入到Bucket1中的文档并发送该文档作为响应。
    • 将审核文档写入bucket2

    一旦失败,

    • 将审核文档写入bucket2。
    • 删除插入到BUCKET1中的文档并引发异常。
    • 将审核文档写入bucket2

    我们编写了一个服务类,并使用两个存储库类将文档保存到couchbase,以及一个webclient调用外部服务。

    我们的服务类方法业务逻辑如下所示。

        {
    
        //1. Validate the request and throw the error
        List<String> validationMessages = handler.validate(customerRequest);
        if (validationMessages != null && !validationMessages.isEmpty()) {
            return Mono.error(new InvalidRequestException("Invalid Request", validationMessages, null));
        }
    
        //generate the id, set it to the request and save it to BUCKET1
        String customerRequestId = sequenceGenerator.nextId(Sequence.CUSTOMER_ACCOUNT_ID);
        customerRequest.setcustomerRequestId(customerRequestId);
        customerRequestMono = bucket1Repository.save(customerRequest);
    
    
        //2. Call the external service using webclient
        externalServiceResponse = customerRequestWebClient.createCFEEnrollment(customerRequest);
    
        //2. Subscribe to the response and and on Success write audit to BUCKET2 , and onerror write audit to BUCKET2 , and delete the inserted documet from BUCKET1
        externalServiceResponse.subscribe(response -> {
            //Initialise the success audit bean and save
            //2.1 a) Write Audt to BUCKET2
            Mono<CustomerAuditBean> auditResponse = bucket2Repository.save(cfeAudit);
             }, errorResp -> {
            //2.2 a) Write Audt to BUCKET2
            //Initialise the error audit bean and save
            Mono<CustomerAuditBean> auditResponse = bucket2Repository.save(cfeAudit);
    
            //2.2 b)Delete the inserted
            Mono<CustomerRequest> delCustomer = bucket1Repository.deleteByLoanAccountId(loanAccountId);
        });
    
        //Get the loan account id and return the same
        finalResponse = bucket1Repository.findByCustomerId(customerId);
        return Mono.when(externalServiceResponse,customerRequestMono,finalResponse).then(finalResponse)
                .doOnSuccess(resp -> {
                    try {
                        finalMasterAudit.setServiceResponse(new ObjectMapper().writeValueAsString(resp));
                        Mono<CustomerAuditBean> auditResponse = bucket2Repository.save(finalMasterAudit);
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
    
                })
                .doOnError(error -> {
                    try {
                        finalMasterAudit.setServiceResponse(new ObjectMapper().writeValueAsString(error.getMessage()));
                        Mono<CustomerAuditBean> auditResponse = bucket2Repository.save(finalMasterAudit);
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
    
                });
    }
    

    我们观察者的两个问题

    1. 文档在某些情况下是不会持久化的,直到我们订阅它。这是预期的行为吗?是否需要订阅要保存的文档?
    2. 出错时无法删除文档。
    3. 我也知道我没有遵循上面的纯反应编程。帮助我使用任何指针来有效地以反应方式编写代码。

    请帮我们指点一下

  • 共有1个答案

    方安怡
    2023-03-14

    以下是上面的一段代码:

    externalServiceResponse.subscribe(response -> {
        Mono<CustomerAuditBean> auditResponse = bucket2Repository.save(cfeAudit);
         }, errorResp -> {
        Mono<CustomerAuditBean> auditResponse = bucket2Repository.save(cfeAudit);
        Mono<CustomerRequest> delCustomer = bucket1Repository.deleteByLoanAccountId(loanAccountId);
    });
    

    它有两个反应性编程问题:

    1. 您创建的是不订阅的单声道,因此它们永远不会执行。
    2. 无论如何都不应该在subscribe中创建它们,而是使用flatMap或onErrorResume将它们链接起来,进行预订阅。

    类似这样的东西应该能起到作用(请原谅,我还没有测试过它,所以您可能需要做一些调整):

    externalServiceResponse
       // If something goes wrong then delete the inserted doc
       .onErrorResume(err -> bucket1Repository.deleteByLoanAccountId(loanAccountId))
    
       // Always want to save the audit regardless
       .then(bucket2Repository.save(cfeAudit))
    
       .subscribe();
    

    代码中还有其他问题需要解决,例如,在订阅最终的单声道之前,您似乎想要将多个单声道平面映射在一起,但希望这能让您开始。

     类似资料:
    • 我们的应用程序使用的是一个DB,并使用 要从存储桶中删除记录,我们在存储库中创建了以下方法: 我们在桶上也有相关的索引: 我们的代码在尝试删除元素时使用分页: 但是,很多时候我们得到超时 删除狗的第0页 o.s.s.s.TaskUtils$日志记录错误处理程序:计划任务中发生意外错误。 由于以下 n1ql 错误,无法执行查询:{“消息”:“超时 7.5 秒超过”,“代码”:“超时超过 7.5 秒”

    • 我是沙发基地的新手。我在我的应用程序中使用spring,我试图通过它连接到本地的couchbase。我试图在配置中创建一个couchbase模板(类似于在mongo模板中所做的事情),如下所示: Spring配置

    • 问题内容: 现在已经苦了两天,只是不能删除文件 在这里,我将放置将进行测试的代码,希望有人可以指出我做错了的事情,以及已经尝试过的事情: 将Lucene版本从更新为 使用代替 特林的配置为或 这里的代码: 首先将在中生成索引,并 显示将成功查询该索引,然后希望删除该文档,但再次将证明删除操作失败。 这是pom依赖关系,以防有人可能需要测试 渴望得到答案。 问题答案: 您的问题出在分析仪中。将标记定

    • 问题内容: 使用标准JavaScript删除元素时,必须首先转到其父元素: 首先必须去父节点对我来说有点奇怪,JavaScript是否有这样的原因? 问题答案: 我知道,增强本机DOM功能并不总是最好的或最受欢迎的解决方案,但是对于现代浏览器来说,这很好。 然后你可以删除这样的元素 要么 注意:此解决方案不适用于IE 7及更低版本。有关扩展DOM的更多信息,请阅读本文。 编辑:回顾我在2019年的

    • viewuser.jsp 你好,我有问题在删除用户。它显示执行后输出失败。我认为它没有从ViewUser中获取用户名。请帮帮我.查询正常,数据库连接仍有问题,取用户名并删除。谢谢你!

    • 这里已经提出并回答了类似的问题。解决方案是将日志记录级别从组织:: 我的情况的不同之处在于,我使用的是被动支持,上面的坏男孩不起作用。我还尝试将 中的所有内容都设置为 DEBUG,但仍然无法在日志中看到任何查询。 我想反应式存储库有一些特别的地方,我没有提到。任何想法都非常欢迎!