1. yykamei's Podcast
  2. #79 Rails で CQRS と Event S..
2025-10-20 14:36

#79 Rails で CQRS と Event Sourcing をするのはやっぱり Rails っぽくない

最近、改めて CQRS と Event Sourcing の勉強をしました。

サマリー

RailsでCQRSとイベントソーシングを実装することは、Railsの一般的な利用方法から逸脱していることが強調されます。イベントソーシングの利点や課題について、特にデータの永続化とアプリケーションのスケーラビリティに関する議論が行われています。

00:01
10月の20日になりました。
ちょっと前まで暑かったような気がするんですけど、もうすっかり冷えてきましたね。特に朝方はもう冷えてる感じですね。はい。涼しいとかじゃなく、もう冷えてる感じがします。
で、まあ体調もいいしね。
まずは風邪をひいて、なんか喉がおかしい気がしますね。
Railsの特徴とイベントソーシング
で、今回はですね、Rails で CQRS と Event Sourcing をするのはやっぱり Rails っぽくないということで、やらせてもらおうと思うんですけど、
あの、
Ruby on Rails っていうフレームワークを使ってお仕事をすることが私は多いんですけれども、
そうですね。
だいたいRails っていうのは、そのクラッド、CRUD のあれですね、作成のクラッドを使って、
クラッドを使って、クラッドを使って、クラッドを使って、クラッドを使って、クラッドを使って、クラッドを使って、
そうですね。
だいたいRails っていうのは、そのクラッド、CRUD のあれですね、
作成、読み取り、更新、削除みたいな、その4つを前提にしているフレームワーク、
まあというよりはリソース志向のフレームワークって言った方がいいですかね。
なんですけど、
やっぱり、作成と読み取りだけでやれると、いろいろ都合がいいっていうのはあるらしいっていうのは聞いていて、
そのうちの一つがイベントソーシングだと私は理解してるんですよね。
イベントソーシングっていうのは何かというと、アプリケーションのライフサイクル全体に渡って、
イベントっていうものを定義して、注文されたとか、注文がキャンセルされたとか、
ですよね、例えばECサイトだと。
あるいはそのカートに商品が積まれた、カートから商品が削除されたとか、
そこら辺のイベント全てを記録して、その記録したイベントのイベントストアって言うんですよね。
イベントストアから集約、DDDみたいな集約ですよね、アグリゲートを生成することができれば、最新の状態が手に入るし、
ある時点の集約を手に入れたければ、ある時点にタイムトラベルしてその状態を再現できるというところで、
考え方としては非常に面白いなとは思うんですけど、
イベントソーシングっていうのはですね、全部のイベントをストアしていくので、
それはそれで今度、新しいイベントを追加するときに、集約に何かを任せてビジネスロジックを実行してやるというときに、
過去の状態を見て何かしらそのバリデーションしたりみたいなのが必要になったりするんですよね。
そうじゃないこともあるんですけど、そういった時にイベントストアから全部のイベントを持ってきて、
最新の集約に再現して、そこからバリデーションを走らせていって、全部のイベントを持ってくるっていうのが、
そうですね、なかなかなんですよね。
もちろんまだプロトタイプレベルだとか、あとはデータベースを使わずに、
イベントソーシングはデータベースを使わずにメモリ上で配列でイベントを持っておいて、
イベントを全部保持しておいて、その都度その都度そのイベントを参照するっていう風にすればかなりできると。
だからアプリケーションを具体的なインフラとかをかませずに検証するみたいなのに非常に便利らしいというのはあるんですけど、
イベント全部読み取るっていうのが、メモリがだんだんだんだんね、現在はもう潤沢になっているとはいえ限界があると。
そうするとやっぱりデータベースに保存して永続化したくなると。
永続化しても件数が今度大きいと結構イベントを再現するのに時間がかかるんですよ。
例えばすごくトラフィックがヘビーなアプリケーションだとイベントが1日に10万とかあるいは100万とかのイベントが発生してもおかしくないと思うんですよね。
そうなってくると簡単に億以上のレコード数になるような気がするんですよ。
これをメモリ上でやるのはやっぱり無理なんで永続化するんですけど、永続化したところで億以上のレコードを全部持ってきてそれで再現するのって、
なかなか時間かかるよなと。工夫すればもちろんできるんですけど時間はどうしても避けられないなと。
というところでイベント送信をやるにあたってスナップショットを使うとかいうのがあるらしいんですよね。
スナップショットっていうのはある時点でのイベントの状態を基にしたアプリケーション全体の状態をダンプしたものって言い方ですかね。
になるらしいんですよね。
それがまあそういう工夫が必要になるんですよね。
CQRSの導入と課題
あと今イベント送信だけの話をしましたけど、これをCQRSと組み合わせるっていうところになるんですよね。
CQRSっていうのはコマンドクエリリスポンシャビリティセグリゲーションですかね。
要は書き込みと読み取りっていうのの責務を明確に分離してきっちりありましょうみたいな。
そうするとイベント送信とCQRSを組み合わせるときにだいたいコマンド側でイベント送信の実装をするわけですよ。
イベント送信のスナップショットを使ったりしてコマンド側でいい感じにイベントを追記していくと。
コマンド側がトリガーになってイベント送信にイベント追加していって、その後にイベントが発行されたという状態をおそらくリード側にも反映しないと
リード側のデータベースは明確に分ける場合は別のデータベースだと思うんですけど、とにかくリード側にも反映させる必要があって
それが非同期であるのか同期であるのかはともかくそんな感じでイベント経由でリード側に伝わると。
リード側はそのイベントを受け取って自身のデータベースというかリード専用のロジックというかデータベースクエリを構築するための状態を作るということらしいですよね。
そのあたりをプロジェクターとかいうんですかね、投影みたいな作業があるらしいと。
CQRSのR部分もあって、これで全体的にはCQRSプラスイベント送信という実装になるんですけど、これをRuby on Railsで試しにやってみたわけですよ。
全然Railsっぽくないと、もう本当にRailsの良さを完全に捨ててるんですよね。
これによって得られる何かはきっとあるんでしょうけど、ちょっと現実問題、これをチーム開発でやるのは厳しいなというのがありますよね。
RailsはRailsっていうレールがもうすでにあって、そこから完全に外れてるわけですよ、CQRSとイベント送信っていうのは。
開発者のメンタルモデルとしてRailsやってるからRailsってなんとなくこうだよねっていうのがあって、
そこからモデルはこういうふうに作るよねとか関係性はこうだよねとかいうふうに定義していくんですけど、
CQRSになると、モデルをいきなり作るっていうよりは最初にイベントありきで考えるんで、
アクティブレコードの音形は完全に得られない、ほとんど。
アクティブレコードパターンってやっぱり結構認知負荷を下げるというか、言ってしまえば結構簡単なんですよね、シンプルなんですよね。
それが後々のスケーラビリティに影響するだとか、更新されてしまうとデータの変更をトラッキングできないみたいなのがあったりするかもしれないんですけど、
でも非常にアプリケーションをわかりやすく作るという点では非常に優れてるなって思うところなんですよね。
じゃあなんでCQRSとイベントソーシングしたいのかっていうのが、一つにはスケーラビリティみたいなのが言われてたりしますよね。
特にCQRS側でスケーラビリティが求められると、これはイベントソーシングというかCQRSの方ですね。
コマンドとクエリーが分かれることによって、クエリーはクエリーに特化した、あえて非正規化したデータ構造を持つことによって、
ヘビーな参照に耐えると、コマンドはコマンドで自分の責務を全うすると。
イベントソーシングの目的は、タイムトラベルできるとかは目的ではないと思うんですよね。
副次作用的なあれかな。やっぱり履歴的なところは大きいんですかね。
履歴、そうですね。ドメイン駆動設計を始めるにはイベントソーシングではなくて、イベント履歴式なんとかみたいな、あえてそういう言葉を使うようにみたいにはコラムにも書いてあるぐらい。
履歴っていうのがやっぱり目的としては大きいんでしょうね。
履歴目的であれば、クラットで何かを更新するとか何かを作成するタイミングで履歴用のテーブルみたいなのがあって、
それに保存、トランザクションを一緒に保存するでもいいんじゃないのっていう気もしなくはないんですけどね。
イベントソーシングの根源にはイベントソース、つまりイベントストアが唯一の信頼できる情報源で、
これを参照しさえすれば最新の集約を手に入れられるっていうのがあって、
おそらくクラットでついでに履歴っぽいテーブルにレコードを作成するのって、
よっぽど注意しない限りイベントソーシングの信頼できる唯一のソースっていうところにはならないというような気はしますよね。
なんですけど、本当に信頼できる唯一のソースであるイベントストアが実際のアプリケーションで求められているのかっていうと、
まあわからないなっていうところですね。もちろんあると便利なのかもしれないですけど、
今までの業務アプリケーションというかその仕事の中でそこまで必要になったケースは見たことがあんまりないですかね。
履歴はあってしかるべきだよねっていうのはそれはそうで、実際ログとか見ますからね。
ログではなくてそもそもどういったイベントなのか、どういった経緯によってデータが書き込まれたのかみたいな、
そういうのは確かに知っておきたいなっていうのはあるので、
関査とかそういう観点では履歴って本当に大事なんですけど、
イベントソーシングじゃないとダメかっていうとわからないなっていうところですね。
ちょっとまだ私がイベントソーシングを勉強し始めたばかりっていうのがあって、
真髄に迫れてないっていうのがあるかもしれないですね。
Railsでの実装の検討
ただ断言したいぐらいなんですけどレールズでイベントソーシングはマジでレールズっぽくないから、
なんか考えた方がいいかなと。
レールズでイベントソーシングもしするんだったらとにかくそのイベントソーシングにまつわる概念をしっかり抑えて、
レールズっぽいインターフェース、例えばセーブとかアップデートとか、
私が結構レールズっぽいのはやっぱりバリデーションと、
コントローラーからモデルにデータを渡す時のマスアサインメントとかですかね、
あんあたりをやりつつイベントソーシングっぽさを出す。
CQRSするのかな、でもCQRSするともっと酷いというかレールズっぽさがなくなるんだよな。
どちらかというと、だいたいイベントソーシングやるって言ったらCQRSもやるよねみたいな。
なぜかというとプロジェクションしてリード側にクエリー側ですかね、
がなるべく素早く参照のレスポンスを返せるようにみたいなところなんですけど、
レールズだったらもしかしたらイベントソーシングだけでいいのかもしれないですね。
CQRSは一旦置いといて、イベントソーシングをもうちょっと学んでみると楽しそうな気がしました。
ということで今回はレールズでCQRSとイベントソーシングをするのはやっぱりレールズっぽくないでした。
それではまた。
14:36

コメント

スクロール