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

在命令中尝试对佐贺模式做出反应之前应用状态

隆安然
2023-03-14

在我看来,传奇模式在很多方面都是聚合模式的倒置。首先将命令处理成域事件,然后在聚合的情况下将此域事件应用到状态中是很有用的,但我认为在saga的情况下,域事件是已经发生的事情的文档,应该在试图对状态做出反应之前应用到状态中。

现在我的问题是:对于Commanded.processmanagers.processmanager模块,有没有一种方法可以将命令配置为首先apply,然后handle?或者这是一个严重的bug,需要在一般情况下进行修复?

共有1个答案

岑元徽
2023-03-14

按照设计,在处理/2之后调用apply/2回调,不可能将命令配置为具有不同的行为。

我同意您的推理,即在尝试处理事件以产生任何命令之前,将事件应用于流程管理器的状态更有意义。这似乎是一个值得对命令进行的更改,可以通过您已经提出的问题(#176)进行跟踪。

同时,您可以按照以下方式实现流程管理器(saga):

defmodule InvoicingProcessManager do
  use Commanded.ProcessManagers.ProcessManager,
    name: __MODULE__,
    router: InvoicingRouter

  defstruct [
    :batch_uuid,
    pending_invoice_ids: MapSet.new()
  ]

  def interested?(%InvoiceBatchStarted{batch_uuid: batch_uuid}), do: {:start, batch_uuid}
  def interested?(%InvoiceCreated{batch_uuid: batch_uuid}), do: {:continue, batch_uuid}
  def interested?(%InvoiceFailed{batch_uuid: batch_uuid}), do: {:continue, batch_uuid}
  def interested?(%InvoiceBatchStopped{batch_uuid: batch_uuid}), do: {:stop, batch_uuid}
  def interested?(_event), do: false

  # Event handlers

  def handle(%InvoicingSaga{}, %InvoiceBatchStarted{} = started) do
    %InvoiceBatchStarted{batch_uuid: batch_uuid, invoice_ids: invoice_ids} = started

    Enum.map(invoice_ids, fn invoice_id ->
      %CreateInvoice{
        invoice_id: invoice_id,
        batch_uuid: batch_uuid
      }
    end)
  end

  def handle(%InvoicingSaga{}, %InvoiceCreated{invoice_id: invoice_id}),
    do: attempt_stop_batch(pm, invoice_id)

  def handle(%InvoicingSaga{}, %InvoiceFailed{invoice_id: invoice_id}),
    do: attempt_stop_batch(pm, invoice_id)

  ## State mutators

  def apply(%InvoicingSaga{} = pm, %InvoiceBatchStarted{} = started) do
    %InvoiceBatchStarted{batch_uuid: batch_uuid, invoice_ids: invoice_ids} = started

    %InvoicingSaga{
      transfer
      | batch_uuid: batch_uuid,
        pending_invoice_ids: MapSet.new(invoice_ids)
    }
  end

  def apply(%InvoicingSaga{} = pm, %InvoiceCreated{invoice_id: invoice_id}) do
    %InvoicingSaga{pm | pending_invoice_ids: invoice_completed(pm, invoice_id)}
  end

  def apply(%InvoicingSaga{} = pm, %InvoiceFailed{invoice_id: invoice_id}) do
    %InvoicingSaga{pm | pending_invoice_ids: invoice_completed(pm, invoice_id)}
  end

  ## Private helpers

  def attempt_stop_batch(%InvoicingSaga{batch_uuid: batch_uuid} = pm, invoice_id) do
    pending_invoices = invoice_completed(pm, invoice_id)

    case empty?(pending_invoices) do
      true -> %StopInvoiceBatch{batch_uuid: batch_uuid}
      false -> []
    end
  end

  defp invoice_completed(%InvoicingSaga{pending_invoice_ids: pending_invoice_ids}, invoice_id) do
    MapSet.delete(pending_invoice_ids, invoice_id)
  end

  defp empty?(map_set, empty \\ MapSet.new())
  defp empty?(%MapSet{} = empty, %MapSet{} = empty), do: true
  defp empty?(%MapSet{}, %MapSet{}), do: false
end
 类似资料:
  • 我正在使用中的向已定义的后端发送请求。我想使用作为断路器,但只用于一种用例:如果后端响应代码,我的假客户机应该等待一个小时,直到它再次联系到真正的后端。在此之前,应该执行回退方法。 我必须如何配置我的Spring Boot(1.5.10)应用程序才能实现这一点?我看到了许多配置的可能性,但只有很少的例子--在我看来--不幸的是,没有围绕用例解决。

  • 我有一个包含编辑选项的帐户表。单击编辑选项时,将显示帐户编辑模式对话框。用户可以通过单击右上角的“X”或单击关闭按钮来关闭或取消编辑。当模式关闭时,我想清除一些状态属性,包括对话框属性和父组件属性。对话框属性更新没有任何问题,但我收到这个错误时,父属性试图更新: 无法在现有状态转换期间更新(例如在

  • 每当我在输入命令npx react native run android后尝试测试应用程序时,就会出现以下错误。我试着在环境变量中设置路径。但仍然不起作用我尝试重新安装react native,但仍然不起作用。我试图从java重新安装JDK,但最后,该应用程序仍然无法在模拟器中运行。感谢您的反馈:) 失败:生成失败,出现异常。 出错的地方:任务执行失败:react-native-community

  • 我有一个前端webapp开发与React JS,和RestAPI与Spring Boot。当我试图从我的反应应用程序访问API时,我得到一个403错误。我的API Rest部署在tomcat服务器中。

  • 问题内容: 以下是React中的反模式吗?我喜欢这种模式,因为当实例化一个组件时,它在静态函数中为我提供了上下文。然后,我可以导入该类并调用静态方法来修改状态。还是可以通过更好的方式来完成? 问题答案: 显然,这取决于条件,可能是一种反模式,也可能是一个错误。静态类方法不应与类实例一起使用。绑定到特定的组件实例和用途,这只能证明类是单例是合理的(尽管单例也经常是反模式)。如果期望有多个类实例,那么

  • 问题内容: 当我向某个服务器发送请求时,将出现303响应,然后是请求的响应以及200状态代码。有趣的是,我只能在开发人员控制台的网络视图中看到此内容。当检查我的$ .ajax()请求的状态码和响应时,将有第二个请求的响应以及200 http状态码。 问题在于,似乎第二个请求正在缓存(尽管状态码为200),我真的需要它不可缓存。因此,我真的很想干预使用http 303状态代码进行的转发过程。我希望我