AASMでステータス変更と同じクリティカルセクションで実行

Ruby

概要

  • 主にActiveRecordと併用して使うステータス管理用のgemがあります。
  • AASM(ステートマシーン)です。
  • 「ステータス変更と同時に別の処理を実行したい」という要求を満たすために排他制御(主にデータベースのトランザクション)を使う場面がありますが、どのコールバックを使うのかがAASMのドキュメント内で明示されていなかったので書いておきます。

問題

  • よくAASMのサンプルコードで見つけるのが、after_commitコールバックに処理をしたいメソッドを書く方法です。
AASM - classの状態遷移をスマートに実装するためのgem (Ruby, Active Record, Sequel, Mongoid) - Qiita
AASM - Ruby state machines ここを参考にしました。
  • 上記にあるコードでは、ステータスの変更が終わったら通知をするというような別に処理を行っても問題ない処理なのでコードは正しいです。
  • 要するに、after_commitはその名の通りAASMによって管理されているステータスが更新されたことをDBにコミットした後に実行されます。

  • しかしながら、AASMで管理するステータスと別のテーブルにあるステータスを同時に更新する場合にafter_commitコールバックを使うだけでは不十分です。

アプローチ

after コールバックを使います。

afterコールバックを使うと、AASMで管理するステートと同じトランザクション内で実行されます。

aasm/aasm.rb at master · aasm/aasm
AASM - State machines for Ruby classes (plain Ruby, ActiveRecord, Mongoid, NoBrainer, Dynamoid) - aasm/aasm.rb at master...

afterコールバックは、eventとtransitionに対して設定できます。

余談

requires_lock: trueは付ける必要があります。

コメント