Skip to content

Railsのtransaction内でメール送信を行ったらループ送信が発生した話

障害対応の中でtransactionの使い方に関する学びがあったので記録します。

transaction処理でDB操作以外は行わない

Railsのtransaction内でメール送信を行ったところ、エラー時にメールが繰り返し送信される問題が発生しました。
ActiveRecordのtransactionではメール送信はrollbackしないため、DBの送信履歴と不整合が起きていました。

rollbackできる処理とできない処理

rollback可能な処理

  • ActiveRecordによるDB更新(Model.create や Model.updateなど)
  • ValidationErrorによるrollback
  • 例外を投げるメソッドで失敗した場合
    (save! や update!のActiveRecord::RecordInvalidなどの例外発生)

rollback不可能な処理

  • メール送信(ActionMailer)
  • 外部APIコール
  • DB以外のファイルの書き込み

DB操作のみtransaction内に残し、それ以外は別処理へ移動

transactionでrollbackしない処理は、別処理として切り出しました。
変更後の例は以下です。

ruby
obj.each { |arg|
  begin
    DBの更新1
    DBの更新2
    DBの更新3
  rescue => e
    error出力
    next
  end

  begin
    メール送信
  rescue => e
    error出力
  end
end