我有一个演员(人),我希望能够在状态期间存储消息。问题是我不确定如何最好地实现这一目标。
假设我有一些命令。
ChangeAddress
ChangePhoneNumber
BeginMove
FinishMove
当我处于移动过程中(在BeginMove开始之后和FinishMove之前)我想阻止更新Address和PhoneNumber,并在移动完成后重放任何事件。我使用的是ReceivePersistentActor,每个命令都是不同的类。
现在我正在考虑演员的状态标志,但是成为/不成功的功能会更自然,但却无法看到如何将它应用于不同的命令。
另外,作为一个侧面问题,有一个很好的模式可以分解必须写入的命令和恢复数量,因为演员需要处理更多的命令/事件吗?
答案 0 :(得分:3)
Akka已经内置了这个:
http://getakka.net/docs/working-with-actors/Stashing%20Messages
您可以在收到消息时将消息存储在一个状态,然后在准备好转换到相关状态时解除消息。然后,隐藏的邮件将转到邮箱的前面进行处理。
在您的示例中,您将收到BeginMove
命令并通过调用Become(Moving)
转换为移动状态。下次处理邮件时,您将处于此新状态。在您的Moving方法中,您将配置Receive<ChangeAddress>
消息处理程序来隐藏消息和所有其他处理程序,以便在移动时拥有您想要的任何行为。在将来的某个时刻,您需要一个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。
解决问题的一种方法是在适当的时候将行为委托给儿童演员,但在那个阶段它变成了更多的设计问题。
答案 1 :(得分:0)
首先要做的事情是:只要没有PipeTo()调用 - 就没有什么可以改变的。
每个参与者一次处理一条消息,因此当它获得一个请求列表时,它们将按顺序逐个接收顺序处理。
为了避免在处理长时间运行的呼叫时出现中断(比如使用数据库) - 我正在堆叠我的演员 - 请参阅接收演员的示例。这允许:
避免使用藏匿,因为它不需要
public class ProcessActor : ReceiveActor{
public ProcessActor() {
Receive < ChangeAddress > (
message = > {
BecomeStacked(ProcessingOrDoNothing);
//{do the job here}
UnbecomeStacked();
});
}
public void ProcessingOrDoNothing(){}
}