【问题标题】:akka.net Stashing messages during a specific state of an actorakka.net 在参与者的特定状态期间存储消息
【发布时间】:2016-08-20 15:23:10
【问题描述】:

我有一个演员(Person),我希望能够在某个状态期间存储消息。问题是我不确定如何最好地做到这一点。

假设我有一些命令。

ChangeAddress
ChangePhoneNumber
BeginMove
FinishMove

当我正在移动时(在 BeginMove 开始之后和 FinishMove 之前),我想阻止对 Address 和 PhoneNumber 的更新,并在移动完成后重播任何事件。我使用的是 ReceivePersistentActor,每个命令都是不同的类。

现在我正在考虑在 actor 上设置一个状态标志,但虽然成为/不成为功能会更自然,但不知道如何将其应用于不同的命令。

作为一个附带问题,是否有一个很好的模式来分解必须编写的命令数量和恢复,因为参与者需要处理更多命令/事件?

【问题讨论】:

  • 我已经用我认为你需要的流程更新了我的答案

标签: akka.net


【解决方案1】:

Akka 已经内置了这个:

http://getakka.net/docs/working-with-actors/Stashing%20Messages

您可以在收到消息时将它们存储在一种状态,然后在您准备好转换到相关状态时取消存储。然后将隐藏的消息转到邮箱的前面进行处理。

在您的示例中,您将收到BeginMove 命令并通过调用Become(Moving) 转换到移动状态。下次处理消息时,您将处于此新状态。在您的 Moving 方法中,您将配置 Receive<ChangeAddress>message 处理程序以存储消息,并且所有其他处理程序在移动时具有您想要的任何行为。在未来的某个时候,您需要一个FinishMove 命令,将您的行为改回开始移动之前的状态并取消隐藏所有消息。此时,所有隐藏的消息都将开始以您的原始行为状态进行处理。 这都是非阻塞的

void OriginalState()
    {
        Receive<ChangeAddress>(s =>
        {
             // change address logic
        });

        Receive<BeginMove>(msg =>
        {
            Become(Moving);
        }
    }

void Moving()
    {
        Receive<ChangeAddress>(s =>
        {
            Stash.Stash();
        });

        Receive<FinishMove>(msg =>
        {
            Become(OriginalState);
            Stash.UnstashAll();
        }
    }

有关如何配置状态以处理消息类型的更多示例代码,请参阅 switchable behaviours

一种分解方式是在适当的情况下将行为委托给子角色,但在那个阶段它更多地成为设计问题。

【讨论】:

    【解决方案2】:

    首先要做的事:只要没有 PipeTo() 调用 - 没有什么可改变的。

    每个参与者一次处理一条消息,因此当它获得一个请求列表时,它们将按接收顺序,一个接一个,按顺序处理。

    为避免在处理长时间运行的调用时出现中断(例如使用 db) - 我正在堆叠我的演员 - 请参阅接收演员的示例。这允许:

    1. 停止处理收件箱
    2. 阻止调度程序停止方法(超时)
    3. 避免使用存储,因为它不需要

      public class ProcessActor : ReceiveActor{
      
       public ProcessActor() {
      
          Receive < ChangeAddress > (
              message =  > {
                  BecomeStacked(ProcessingOrDoNothing);
                  //{do the job here}
                  UnbecomeStacked();
              });
       }
      
        public void ProcessingOrDoNothing(){}
      
      }
      

    【讨论】:

    • 您能否详细介绍一下成为堆叠和未成为堆叠的功能?可以发一下代码吗?
    • 那些是akka内部的,用于改变actor状态。当状态发生变化并且没有Receive 时,邮箱处理将停止,unbecomeStacked 恢复之前的堆叠命令。
    • 好的,谢谢,我已经忘记了这些,因为我一直使用成为。
    • 我认为我缺少的部分是这似乎导致 ChangeAddress 将项目保存在邮箱中,同时仍允许其他 ChangePhoneNumber 消息通过。我还希望在收到 BeginMove 命令时修改 ChangeAddress 行为,并在收到 FinishedMove 命令时修改行为。如果对我想要完成的工作有所帮助,我可以提供一个更完整的示例。
    • 另外,我认为在单个消息处理中调用成为和不成为实际上不会做任何事情,因为只有处理的下一条消息才能获得新的行为? IE。在这个例子中,唯一能做某事的代码是 {do the job here} 部分,因为你在同一条消息中成为和不成为,这相互抵消
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多