干净地验证 RailsEventStore 中的事件模式

Cleanly validating event schemas in RailsEventStore

我正在使用 Rails 和 RailsEventStore 构建一个 CQRS 和事件源应用程序。在 RailsEventStore 中,您似乎应该继承代表来自 RailsEventStore::Event.

的事件的 classes
class UserRegistered < RailsEventStore::Event
  …
end

这个基础 class 公开了一个 event_id、一个数据散列和一个可选的元数据散列。据我所知,这看起来更像是 Greg Young 曾经称之为事件信封的东西,我的域模型应该只关心存储在信封数据哈希中的实际事件。

现在我想对我的事件强制执行一个模式。但似乎 RailsEventStore 希望我为由我的域模型区分的每个事件类型建模 RailsEventStore::Event(信封)的子class。

在信封的子 class 中验证数据散列的内容感觉很老套和肮脏。我总是需要覆盖初始化方法并传递我真正不关心的东西。

class UserRegistered < RailsEventStore::Event
  def initialize(event_id: SecureRandom.uuid, metadata: nil, data: {})
    ensure_valid!(data)

    super(event_id: event_id, metadata: metadata, data: data)
  end

  def ensure_valid!(data)
    raise ArgumentError unless data[:user_id]
  end
end

通过 event.data[:my_attribute] 访问所有事件属性也感觉不太好。为每个信封子添加很多委托方法class 似乎也是一种浪费。

我更愿意建模一个普通的 Ruby 对象或使用 Dry::Struct 之类的东西来对我的事件的内容属性强制执行模式。

class UserRegistered < Dry::Struct
  attribute :user_id, Dry::Types::String
end

我是不是漏掉了什么?如何以干净的方式验证我的事件?

Dry::Struct 模式的示例可以在示例应用存储库中找到:

https://github.com/RailsEventStore/cqrs-es-sample-with-res/blob/e4983433bc5d71252da58a23da9374f17e1d5cb3/ordering/lib/ordering/order_submitted.rb + https://github.com/RailsEventStore/cqrs-es-sample-with-res/blob/e4983433bc5d71252da58a23da9374f17e1d5cb3/ordering/lib/ordering/order_submitted.rb

虽然从 RailsEventStore::Event 继承是最简单的,但这不是必需的。 Protobuf 集成就是一个很好的例子: https://railseventstore.org/docs/protobuf/#defining-events。它更像一个事件信封。

传递给 RES 的事件需要至少响应 event_iddatametadatatypehttps://github.com/RailsEventStore/rails_event_store/blob/cfc91c9cb367e514ba1c6de1a711a7610780b520/ruby_event_store/lib/ruby_event_store/mappers/transformation/domain_event.rb#L9-L12。您还可以在那里看到它是如何从商店加载时实例化的。

当您提供 own mapper 或仅替换负责该转换的 RubyEventStore::Mappers::Transformation::DomainEvent 时,可以更改此行为。

请比较: https://github.com/RailsEventStore/rails_event_store/blob/cfc91c9cb367e514ba1c6de1a711a7610780b520/ruby_event_store/lib/ruby_event_store/mappers/default.rb

对比 https://github.com/RailsEventStore/rails_event_store/blob/cfc91c9cb367e514ba1c6de1a711a7610780b520/ruby_event_store/lib/ruby_event_store/mappers/protobuf.rb