// event.mbt
//! 事件定义
///|
/// 带元数据的事件
pub(all) struct EventMessage[AggregateId, E] {
event : E
event_id : String
aggregate_id : AggregateId
aggregate_version : Int32
correlation_id : String
causation_id : String
user_id : String?
timestamp : Int64
metadata : Json
schema_version : Int32
}
// impl[E] EventMessage[E] {
///|
pub fn[AggregateId, E] EventMessage::new(
event : E,
aggregate_id : AggregateId,
version : Int32,
) -> EventMessage[AggregateId, E] {
{
event,
event_id: @uuid.v4().to_string(),
aggregate_id,
aggregate_version: version,
correlation_id: @uuid.v4().to_string(),
causation_id: "",
user_id: None,
timestamp: @async.now(),
metadata: @json.to_json("{}"),
schema_version: 1,
}
}
///|
pub fn[AggregateId, E, C] EventMessage::from_command(
event : E,
aggregate_id : AggregateId,
version : Int32,
cmd : @command.CommandMessage[C],
) -> EventMessage[AggregateId, E] {
{
event,
event_id: @uuid.v4().to_string(),
aggregate_id,
aggregate_version: version,
correlation_id: cmd.correlation_id,
causation_id: cmd.command_id,
user_id: cmd.user_id,
timestamp: @async.now(),
metadata: cmd.metadata,
schema_version: 1,
}
}
// }
///|
/// 事件流(不可变序列)
pub(all) enum EventStream[AggregateId, E] {
Nil
Cons(EventMessage[AggregateId, E], EventStream[AggregateId, E])
}
// impl[E] EventStream[E] {
///|
pub fn[AggregateId, E] EventStream::to_array(
self : EventStream[AggregateId, E],
) -> Array[EventMessage[AggregateId, E]] {
fn go(
stream : EventStream[AggregateId, E],
acc : Array[EventMessage[AggregateId, E]],
) -> Array[EventMessage[AggregateId, E]] {
match stream {
Nil => acc
Cons(event, tail) => go(tail, acc + [event])
}
}
go(self, [])
}
///|
pub fn[AggregateId, E] EventStream::length(
self : EventStream[AggregateId, E],
) -> Int32 {
fn go(stream : EventStream[AggregateId, E], acc : Int32) -> Int32 {
match stream {
Nil => acc
Cons(_, tail) => go(tail, acc + 1)
}
}
go(self, 0)
}
// }
// pub trait EventApplier {
// /// 应用单个事件
// apply(self: Self,state: S, event: E) -> S
// /// 批量应用事件
// apply_batch(self: Self, state: S, events: Array[E]) -> S
// }
///|
pub(all) enum EventApplier[S, E] {
Single((S, E) -> S)
Batch((S, Array[E]) -> S)
}