假设我有以下情况。有一个UserActor。除了像Id,FirstName,LastName这样的简单属性之外,用户内部状态还包含一个CategoryId,它表示用户对特定类别的依从性。类别本身是一个单独的域实体,它拥有自己的属性。要执行赋值用户到特定类别的操作,我必须确保特定类别实际存在。处理这种保证系统一致性的场景的正确方法是什么?
我正在考虑两种解决方案,但我不确定哪种解决方案比另一种解决方案更差。
第一种解决方案否认了我所相信的一切。第二部分在阶级/演员扩散方面的规模并不太好。此外,如果UserActor是持久性FSM,我不知道如何从这个“等待命令验证结果”回归。 FSM没有不成比例。
我相信如果你将Akka与CQRS / ES方法结合使用,你应该处理这类问题。你是怎么解决的?我读了几本关于阿卡的书,但没有找到任何自以为是的方法。这很奇怪,因为在我看来,这是一个基本的用例。
我真的很感激任何提示。
答案 0 :(得分:1)
您正在尝试防止可能随时发生的无效系统状态。在用户遵守该类别后,可以随时删除该类别。
在分布式环境中,阻止可伸缩系统进入无效状态是不可能的。相反,您应该关注系统如何从无效状态中恢复。在这种特殊情况下,你应该考虑当一个类别被删除并且有一些用户遵守它时,会发生什么(而不是!)。也许你告诉他们X类不再存在或只是悄悄地删除他们的成员?你的商界人士应该告诉你。
您可以在用户执行命令之前检查类别的存在,但仅作为优化,以限制滥用您的数据的滥用用户,而不是在系统架构的核心。
忽略规则“告诉不要问”,并使用Ask协议查询CategoriesActor以确定是否存在具有指定Id的类别?
此规则不适用于此处,但适用于您向Actor询问某些内容然后告诉相同的 Actor根据其告诉您的内容执行某些操作的情况。
P.S。我假设您有一个分布式系统,因为您选择使用Actor模型。
答案 1 :(得分:0)
我略微弯曲了"告诉,不要问"的规则。 Akka.net的Receive和Command方法有一个名为shouldHandle的可选谓词。我做ask
,但在shouldHandle方法中执行了Sender.Tell()
。如果谓词的结果为false,则不会运行您指定的操作。
示例代码:
public MyActor
{
Command<Object>(cmd => HandleObject(cmd), cmd => ValidateObject(cmd));
}
private bool ValidateObject(Object cmd)
{
// Perform validation as necessary... isValid could be anything but needs to be set
if(isValid)
{
Sender.Tell(true);
return true;
}
else
{
Sender.Tell(false);
return false;
}
}
private void HandleObject(Object cmd)
{
// Handle command
}
在上面的代码中,HandleObject
将永远不会运行,除非ValidateObject
返回true。此模式适用于ask
和tell
。我执行ask
的唯一原因是因为我需要通知用户该命令是否未通过验证...否则我会使用tell
而不必担心执行Sender.Tell
。