Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Lagom:命令处理程序中的异步操作_Scala_Asynchronous_Persist_Lagom - Fatal编程技术网

Scala Lagom:命令处理程序中的异步操作

Scala Lagom:命令处理程序中的异步操作,scala,asynchronous,persist,lagom,Scala,Asynchronous,Persist,Lagom,在Lagom中,当命令处理程序必须执行一些异步操作时,您会怎么做?例如: override def behavior = Actions().onCommand[MyCommand, Done] { case (cmd, ctx, state) => // some complex code that performs asynchronous operations // (for example, querying other persistent entities

在Lagom中,当命令处理程序必须执行一些异步操作时,您会怎么做?例如:

override def behavior = Actions().onCommand[MyCommand, Done] {
  case (cmd, ctx, state) =>
    // some complex code that performs asynchronous operations
    // (for example, querying other persistent entities or the read-side
    // by making calls that return Future[...] and composing those),
    // as summarized in a placeholder below:
    val events: Future[Seq[Event]] = ???
    events map {
      xs => ctx.thenPersistAll(xs: _*) { () => ctx.reply(Done) }
    }
}
这样的代码的问题是编译器希望命令处理程序返回
Persist
,而不是
Future[Persist]

是否故意这样做,以确保事件以正确的顺序持久化(即,必须先保存前一个命令生成的事件,然后再保存后一个命令生成的事件)?但是,这难道不能通过对事件偏移量的适当管理来处理吗?这样,日志总是正确地对它们进行排序,而不管它们实际上是在什么时候保存的


在这种情况下,当命令处理非常复杂,需要从命令处理程序发出异步调用时,我们该怎么办?

邮件列表中有一个类似的问题,James给出了答案。

简而言之,CQRS应用程序中的实体是一个一致性边界,应该只依赖于它内部立即可用的数据,而不是外部可用的数据(不调用外部服务)

您可能正在寻找一个名为
的命令扩展
。您收到一个请求,从外部服务收集一些数据,并构建一个包含需要发送到实体的所有内容的命令

当然,您不应该在写端实体内查询读端以做出业务决策。您也不应该对来自其他实体的数据做出业务决策


实体应该能够做出所有决策,因为它是模型的一致性边界

邮件列表上有一个类似的问题,James给出了答案。

简而言之,CQRS应用程序中的实体是一个一致性边界,应该只依赖于它内部立即可用的数据,而不是外部可用的数据(不调用外部服务)

您可能正在寻找一个名为
的命令扩展
。您收到一个请求,从外部服务收集一些数据,并构建一个包含需要发送到实体的所有内容的命令

当然,您不应该在写端实体内查询读端以做出业务决策。您也不应该对来自其他实体的数据做出业务决策


实体应该能够做出所有决策,因为它是模型的一致性边界

在这些情况下,我一直在做的是将PersistentEntityRef传递给异步操作,以便它可以向实体及其那些命令处理程序(不是产生异步计算的那个)发出命令,然后持久化事件


请记住,这些都不是原子性的,因此您必须考虑如果异步操作在发出命令的中途失败,或者如果一些命令成功,一些命令失败,等等,会发生什么情况。您可能需要一些系统故障的重试机制。如果您将命令处理程序构建为幂等函数,它将帮助您处理重复的命令。

在这些情况下,我一直在做的是将PersistentEntityRef传递给异步操作,以便它可以向实体及其那些命令处理程序(而不是生成异步计算的命令处理程序)发出命令然后这些事件就会持续下去


请记住,这些都不是原子性的,因此您必须考虑如果异步操作在发出命令的中途失败,或者如果一些命令成功,一些命令失败,等等,会发生什么情况。您可能需要一些系统故障的重试机制。如果您将命令处理程序构建为幂等函数,它将帮助您处理重复项。

这一切都很好,但当一个聚合可以引用另一个聚合(通常是!)中的实体时,删除级联的一致性边界将成为整个世界。当然,除非完全禁用删除,这可能是一个选项。我想我可以使用preDelete来收集所有阻止删除的实体或所有必须通过级联删除/更新的实体,然后才实际发出执行这些操作的命令。我不知道我是否理解你关于
preDelete
的观点,但请记住以下几点:总体设计与旧式传统CRUD造型大不相同。在开始之前,请确保您了解这一点。首先,您不会从外部操作留在另一个聚合内部的实体。您可以引用than,但仅允许欠它们的聚合更改它们。此外,除非重构模型,否则一致性边界不会移动。没有这样一件事:在这种情况下,我将建立一个更大的边界。你的一致性边界是你的领域,不是别的。是的,是的,当然。任何超出聚合的级联都会阻止删除。但我们仍然需要知道它的存在,我们需要在聚合中生成级联。因此,我们需要查询哪些实体链接到哪些其他实体,以及在哪些聚合中的信息。即使可以只查看给定聚合内部以搜索其自身的相互链接的实体,但仍然需要找出哪些链接要删除,哪些链接要更新,以及哪些链接阻止了操作。这些信息存储在一个模式聚合中,给定的聚合引用该模式聚合,因此无论如何,将来都会有一个操作来获取它。这一切都很好,但当一个聚合可以引用另一个聚合中的实体时(一般来说!),删除级联的一致性边界就变成了整个世界。当然,除非完全禁用删除,这可能是一个选项。我想我可以使用preDelete收集所有阻止删除的实体或所有必须通过级联删除/更新的实体,然后才实际发出执行这些操作的命令。我不知道我是否理解你的观点a