どうもこんにちは。
今回はRailsアプリケーションで使用しているdelayed_jobについてメモしていきます。
delayed_jobってなに?
delayed_jobとは、「バックグラウンドで非同期処理をしてくれるrailsのライブラリ」です。
何に使えるかっていうと、「大量のジョブを処理する時」に使えます!
一番わかりやすい例だと、大量のメール送信を一度に行うとかなり時間がかかってしまうため、小分けにして送信していくという手法をとるために最適です。
導入方法
導入はGemを使用して行います。
1. Gemの追加
Gemfileに以下のコードを記述します。
gem 'delayed_job_active_record'
2. bundle installの実行
ターミナルでbundle install
を実行します。
3. マイグレーションファイルの作成
ターミナルでrails generate delayed_job:active_record
を実行します。
Delayed_jobは、DB上にテーブルを作成してジョブを管理しています。
DBにアクセスすれば溜まっているジョブを確認することもできます。
4. マイグレーションの実行
ターミナルでrails db:migrate
を実行します。
5. ジョブの実行方法を設定
config/application.rb
に以下を記述します。
これによって、ActiveJobのバックエンドとしてdelayed_jobを使用するように指定できます。
class Application < Rails::Application
# ...
config.active_job.queue_adapter = :delayed_job
# ...
end
6. ジョブの実行/停止
以下をターミナルで実行して、delayed_jobワーカーを起動して、ジョブを実行します。
bin/delayed_job start
また、停止するときは以下のコマンドです。
bin/delayed_job stop
使用方法
自分が使用している目的は、メール送信を小分けにして送信することです。今回はそれの使用方法について説明します。
メール送信機能の実装
ある機能のあるタイミングでメール送信ジョブが実行されるようにコードを書いていきます。
以下のコードをメール送信したいタイミングのコントローラに記述します。(例えばコメント登録の後とか。。。)
addresses = ["test01@mail.com", "test02@mail.com", "test03@mail.com"]
addresses.each do |address|
NotificationMailer.send_mail(address).deliver_later
end
次に、app/mailers/application_mailer.rb
に以下のコードを記述します。
class ApplicationMailer < ActionMailer::Base
default from: 'TEST <noreply@test.net>'
layout 'mailer'
end
次に、app/mailers/notification_mailer.rb
にsend_mail
メソッドを定義します。
class NotificationMailer < ApplicationMailer
default from: 'TEST <noreply@test.net>'
def send_mail(send_to_address)
return if send_to_address == []
mail(to: send_to_address, subject: "テストメールです。")
end
end
最後に、app/views/notification_mailer
ディレクトリにsend_mail.html.erb
を作成して、以下のように記述します。
<!DOCTYPE html>
<html lang="ja" dir="ltr">
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type'>
</head>
<body>
<h3><%= "テストメールです。" %></h3>
<p>これはテスト〜\nメール送信のテスト~</p>
<br>
</body>
</html>
バッチ処理実装
次は、ジョブが実行されるようにバッチ処理を組みます。
バッチ処理には、whenever
というGemを導入する必要があります。
その手順は以下の記事でわかりやすく説明されていたので、そちらを参照してください。
whenever
の設定の中で、config
ディレクトリにconfig/schegule.rb
というファイルを作成したと思います。
そこに、Production環境で実行したいコマンドを記述します。(以下は5分おきに実行するという例です。)
every 5.minute do
command "cd /var/app/current && export $(cat /opt/elasticbeanstalk/deployment/env) && bin/delayed_job start"
end
これで5分おきにDelayed_jobが実行されるようになりました。
メール送信の指令はどのようにしてジョブのキューに入るの?
キューとは、ジョブの待ちタスク見たいなものです。
今回の例では、コントローラから「メール送信してくれー」と指示を出しましたが、実はdeliver_later
というメソッドがジョブのキューに入れる役割をしています。
そのため、メールが送信されるまでの順番はこうなります。
デプロイ時に必要な操作
仕上げにデプロイ時に以下のコマンドを実行する必要があります。
# cronを書き換え
bundle exec whenever --update-crontab
# 正常に書き換えられているか確認
bundle exec crontab -e
これは、setupファイルを作成して自動実行でも、ssh接続してコマンド実行でもなんでもOKです。
まとめ
今回はdelayed_jobについて紹介しました。
まだ理解が浅いので、ちょくちょく記事は書き換えると思いますが、参考になったらいいなぁと思います。
以上