Open9
rails_event_store 触ってみる

GitHub
ドキュメント

参考

検証用リポジトリ

Publishing events
stream_name = "order_1"
event =
OrderPlaced.new(data: { order_id: 1, order_data: "sample", festival_id: "b2d506fd-409d-4ec7-b02f-c6d2295c7edd" })
#publishing an event for a specific stream
event_store.publish(event, stream_name: stream_name)
- イベントを発行すると event データと stream データが作成される
-
stream_name
にはオブジェクトを一意に特定できる値を設定(UUID ならそのまま指定)

Subscribing to events
class InvoiceReadModel
def call(event)
# Process an event here.
end
end
subscriber = InvoiceReadModel.new
event_store.subscribe(subscriber, to: [InvoiceCreated, InvoiceUpdated])
- 特定のイベントを購読して処理を実行する

Reading events
scope = client.read
.stream('GoldCustomers')
.backward
.limit(100)
.of_type([Customer::GoldStatusGranted])
- ストリームを指定して全てのイベント or 特定のイベントを取得可能
- 期間指定や最後に特定のイベントが発行された以降などの柔軟な絞り込みができる

Projection
stream_name = "Customer$1"
client.publish(MoneyDeposited.new(data: { amount: 10 }), stream_name: stream_name)
client.publish(custom_event = MoneyDeposited.new(data: { amount: 20 }), stream_name: stream_name)
client.publish(MoneyWithdrawn.new(data: { amount: 5 }), stream_name: stream_name)
account_balance =
RailsEventStore::Projection
.from_stream(stream_name)
.init(-> { { total: 0 } })
.when(MoneyDeposited, ->(state, event) { state[:total] += event.data[:amount] })
.when(MoneyWithdrawn, ->(state, event) { state[:total] -= event.data[:amount] })
account_balance.run(client) # => {total: 25}
- 特定のストリームのデータを全て読み出して現在の状態を射影する
- event_id を指定して特定のイベント以降から射影することも可能

RSpec matchers

少しコードリーディング
Client 初期化時に Subscription インスタンスを登録
initializer で事前に subscriber をイベントに紐づけて登録しておく
publish 時に事前に登録しておいた subscriber を呼び出す