Open9

rails_event_store 触ってみる

ささむくささむく

Publishing events

https://railseventstore.org/docs/v2/publish/

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

https://railseventstore.org/docs/v2/subscribe/

class InvoiceReadModel
  def call(event)
    # Process an event here.
  end
end

subscriber = InvoiceReadModel.new
event_store.subscribe(subscriber, to: [InvoiceCreated, InvoiceUpdated])
  • 特定のイベントを購読して処理を実行する
ささむくささむく

Reading events

https://railseventstore.org/docs/v2/read/

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

Projection

https://railseventstore.org/docs/v2/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 を指定して特定のイベント以降から射影することも可能