#actors #cqrs #event-sourcing

riker-cqrs

为Riker应用程序提供命令查询责任分离

8个版本

0.2.3 2019年1月17日
0.2.2 2019年1月7日
0.1.9 2019年1月3日
0.1.8 2018年10月1日
0.1.0 2018年7月17日

#919 in 异步

MIT 许可证

16KB
275

Riker命令查询责任分离(CQRS)

概述

命令查询责任分离(CQRS)基于事件源,提供了一种更结构化的持久化方法。仅事件源本身适用于在具有固定数量的actor的actor系统中恢复单个actor状态。这可以进一步扩展,以便可以将数据实体建模为actor。例如,一个实体可以是用户、账户、帖子、交易、订单等,其中每个实例都由其自身的actor实例表示。

要更改实体,需要向表示该实体的actor发送命令。例如,要更改用户实体的密码,可以发送UpdatePasswordCmd,或要禁用用户,可以发送DisableUserCmd。当actor收到命令时,它会验证该命令,然后发出一个将被持久化和应用的事件

UpdatePasswordCmd => PasswordUpdatedEvt
DisableUserCmd => UserDisabledEvt

为了帮助设置实体和命令管理,Riker CQRS是一个独立的crate(riker-cqrs),它引入了

  • 实体管理
  • 基于命令的消息传递

由于每个实体都有自己的actor,因此需要有一个协调器,在需要时创建actor并将命令路由到正确的actor。还需要进行基本的簿记,以便actor可以在一段时间的不活动后休眠并从内存中删除,然后在需要处理命令时恢复。

让我们看看如何设置一个表示银行账户的BankAccount的实体管理器

Cargo.toml:

[dependencies]
riker = "0.1.8"
riker-default = "0.1.8"
riker-cqrs = "0.1.8"

代码

use riker::actors::*;
use riker_default::DefaultModel;
use riker_cqrs::*;

let model: DefaultModel<TestMsg> = DefaultModel::new();
let sys = ActorSystem::new(&model).unwrap();

let em = Entity::new(&sys,
                    BankAccountProps,
                    "BankAccont",
                    None).unwrap();

在此,创建了一个Entity,它将管理所有银行账户实例。如果需要,它将创建新的actor并路由命令。

让我们创建一个新的银行账户并进行首次存款

let number = "12345678";
let name = "Dolores Abernathy";

// create bank account
let cmd = CQMsg::Cmd(number.into(), Protocol::CreateAccountCmd(name.into()));
em.tell(cmd, None);

// deposit $1000
let cmd = CQMsg::Cmd(number.into(), Protocol::DepositCmd(1000));
em.tell(cmd, None);

命令需要一个ID,根据该ID,实体管理器将路由命令到该ID的actor。如果没有在内存中为该ID提供活动的actor,则管理器将启动一个actor。在处理命令之前,将加载与该ID相关的任何事件并恢复actor状态。

而不是直接使用actor_of管理actor创建,实体管理器会这样做。您会注意到示例中的Entity::new传递了BankAccountProps。这是一个实现EntityActorProps trait的结构体。

由于每个实体演员都需要自己的唯一ID,因此用于 actor_of 的标准 Props 是不够的。相反,实现了 EntityActorProps

struct BankAccountProps;

impl EntityActorProps for BankAccountProps {
    type Msg = Protocol;

    fn props(&self, id: String) -> BoxActorProd<Self::Msg> {
        Props::new_args(Box::new(BankAccountActor::new), id)
    }
}

依赖项

~8MB
~156K SLoC