Чистая проверка схем событий в RailsEventStore - PullRequest
1 голос
/ 09 июля 2019

Я создаю CQRS и приложение на основе событий с Rails и RailsEventStore. В RailsEventStore кажется, что вы должны наследовать классы, которые представляют события от RailsEventStore :: Event.

class UserRegistered < RailsEventStore::Event
  …
end

Этот базовый класс предоставляет event_id, хеш данных и необязательный хеш метаданных. Насколько я понимаю, это больше похоже на то, что Грег Янг однажды назвал конвертом события, и моя модель предметной области должна заботиться только о реальном событии, которое хранится в хэш-памяти данных конвертов.

Теперь я хотел бы применить схему к моему событию. Но похоже, что RailsEventStore хочет, чтобы я смоделировал подкласс RailsEventStore :: Event (конверт) для каждого типа события, различающегося моей моделью домена.

Проверка содержимого хэша данных в подклассе конверта кажется хакерской и грязной. Мне всегда нужно переопределить метод инициализации и передать то, что мне действительно безразлично.

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]. Добавление большого количества методов делегирования для каждого подкласса конверта также представляется бесполезным.

Я бы предпочел смоделировать обычный объект Ruby или использовать что-то вроде Dry :: Struct, чтобы применить схему к атрибутам содержимого моего события.

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

Я что-то здесь упускаю? Как я могу проверить свои события в чистом виде?

1 Ответ

1 голос
/ 15 июля 2019

Пример схемы 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_id, data, metadata и type: https://github.com/RailsEventStore/rails_event_store/blob/cfc91c9cb367e514ba1c6de1a711a7610780b520/ruby_event_store/lib/ruby_event_store/mappers/transformation/domain_event.rb#L9-L12. Вы также можете увидеть, как он создается при загрузке из магазина.

Это поведение может быть изменено, если вы предоставите свой собственный маппер или просто замените 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

...