導入 ( ぼくのRails開発環境事情 )
「ユーザー登録時にwelcomeメールを送る」みたいな機能があると、
ユーザーを生成するたびにメール送信処理が走ります。
class User
after_create :send_welcome
...
private
def send_welcome
UserMailer.welcome(self).delivey_later # => ActiveJobが非同期にメールを送ってくれる
end
end
User.create!(...) # => Welcome メールが飛ぶ!
開発環境では、letter_opener
を使っているので、実際にメールサーバーを叩いたりはしないようになっています。
gem 'letter_opener'
Rails.application.configure do
...
# letter opener
config.action_mailer.delivery_method = :letter_opener
...
end
が、代わりにブラウザに新しいタブが開くわけです。
User.create!(...) # => ブラウザに新しいタブが開く
問題
そんな時、まとめてユーザーを1000人作ったりすると一斉にメールが開きます。
1000.times { User.create!(...) } # => ブラウザに新しいタブが1000個開く
ブラウザに1000個タブが一気に開いたら普通に考えてメモリ食いつぶして死にます。
何とかしなければ。
解決方法
で、端的に解決方法。
ActionMailer::Base.perform_deliveries = false
ActiveJob::Base.queue_adapter = :inline
1000.times { User.create!(...) } # => メールが飛ばないやったー!
かいせつ
最初はActionMailer::Base.perform_deliveries = false
だけでいけるかと思ったのですがダメでした。
なんでかというと、バックグラウンドジョブ自体は、別プロセスで動いているので...
$ bin/rails c # => プロセス1
$ bin/rake jobs:work # => プロセス2
.deliver_later
してしまうと、そちらに処理が飛ばされてしまい、ローカルで上書きした設定は反映されないのです。
(deliver_layerはActiveJobとActionMailerの連携したメソッドです)
なんとかして同じプロセス上でActiveJobが走らせればいいわけで、
それがActiveJob::Base.queue_adapter = :inline
になります。
ActiveJob::QueueAdapters::InlineAdapter
は、そのプロセスで即時実行するキュー戦略なので、その場で処理が起動して、めでたく、上書きした設定で処理を進めてくれます。
書いてから思ったけど、完全に自分の環境依存の問題な気がした。