20个版本 (11个重大更新)
0.15.0 |
|
---|---|
0.13.3 |
|
0.9.0 | 2020年7月31日 |
#7 in #riker
155KB
669 代码行
RikerES
一个旨在比“照本宣科”更实用的、基于事件溯源和CQRS的抽象。它建立在轻量级actor框架Riker之上。
警告 目前质量相当初阶,功能尚不完整,API仍在变化。
如何使用
此库为Riker添加了一些额外的事件溯源相关概念,实体代表一个领域,并且是处理外部命令和业务逻辑的入口点。使用通常的Riker机制(见创建actor)通过Entity
actor创建。
let entity = actor_system.actor_of_args::<Entity<MyEntity>, _>("my-entity", SomeArgs)`;
定义您的实体
MyEntity
是一个用户提供的、实现了 ES
特质的结构体。
struct MyEntity;
#[async-trait]
impl ES for MyEntity {
type Args = SomeArgs; // the arguments passed to the constructor
type Model = MyData; // The "aggregate" is the data that is to be persisted along with its updates.
type Cmd = MyEntityCommands; // The external command or commands(often in the form of an enum) this entity can handle.
// type Event = (); // TODO: Similar to commands but for handling events emitted by other entities.
type Error = MyEntityError; // Error produced by the handler functions.
// Used to construct an entity, receives the `Entity` actor's context
// to be able to create other actors and hold their references
fn new(_cx: &Context<CQRS<Self::Cmd>>, _args: Self::Args) -> Self {
MyEntity
}
async fn handle_command(
&mut self,
cmd: Self::Cmd,
) -> Result<Commit<Self::Model>, Self::Error> {
// do your command handling here and return a commit that will be persited
// to the configured store(a simple memory store atm).
// when entities are created for the first time
Ok(Event::Create(MyData).into())
// or to update an existing entity
// Ok(Event::Change("some id".into(), MyDataUpdate).into())
}
}
聚合和重新加载实体的状态
定义您的聚合(数据模型),它可以处理的更新以及如何应用它们。
struct MyData {
some_id: String,
some_field: String,
other_field: Option<String>
}
enum MyDataUpdate {
TheChange(String, String),
LittleChange(String),
}
impl Model for MyData {
type Change = MyDataUpdate;
fn id(&self) -> EntityId {
self.some_id.into()
}
fn apply_change(&mut self, change: Self::Change) {
match change {
MyDataUpdate::TheChange(field, other) => {
self.some_field = field;
self.other_field = Some(other);
},
MyDataUpdate::LittleChange(field) => {
self.some_field = field;
},
}
}
}
分发命令和查询
RikerES提供了一个实体管理器,它将保留对已注册实体的引用,并提供一个更简单的API来向正确的实体发送命令和查询。
let mgr = Manager::new(actor_system).register::<MyEntity>(SomeArgs);
let id = mgr.command(MyEntityCommands::DoSomething).await;
let data = mgr.query::<MyEntity>(id).await.unwrap();
依赖关系
~12MB
~214K SLoC