実装に必要な最低限の知識
good_jobとは
Ruby on Railsアプリケーションでバックグラウンドジョブを実行するためのGemです。
good_jobはActive_jobを基本としているので、忘れていたらActive_jobについてさらっと目を通すと理解が深まります。
実際の手順
未来の自分のために手順をそのまま残しておきます。
初期設定
gemを導入
gem 'good_job'
bundle install
good_jobがRailsアプリケーションに統合されるための初期設定
ターミナルでコマンドを実行します。
bundle exec rails generate good_job:install
このコマンドで、いくつかファイルがgenerateされます。
まず1つ目にマイグレーションファイルが生成されます。
先ほどの記事の内容になりますが、
ジョブを実行する際は通常、Ruby on Railsアプリケーションの他にバックエンドインフラを起動して準備しておく必要です。
good_jobではApplicationで使用しているデータベースでキューを管理することができるようにするので、そのために必要なジョブテーブルをDBに作成するためのマイグレーションファイルが作成する必要があります。
ということでマイグレーションファイルを生成したらそのままマイグレートします
bundle exec rails db:migrate
2つ目に'config/initializers/good_job.rb'ファイルも生成されます。こちらでgood_jobの設定(定時処理の設定)を行うことができますが一旦スルーします。
ActiveJobのバックエンドをGoodJobに変更
次にconfig/application.rbにてActivejobの実行をgood_jobに変更します。
module HogeHogeApplication
class Application < Rails::Application
config.active_job.queue_adapter = :good_job # この行を追記
end
end
これで最低限の初期設定は完了しました。
config/initializers/good_job.rbにて定時にジョブを実行するように設定(cronジョブの設定)
こちらの記事を参考にしました
先ほどのgenerateコマンドで自動生成されたconfig/initializers/good_job.rbに必要な初期設定をしていきます。
Rails.application.configure do
config.good_job[:enable_cron] = true # good_jobが実行できる様々なジョブの内、cronを有効にしている
config.good_job[:cron] = {
my_hoge_task: { # 有効にしているcronジョブの名前
cron: '0 0 * * *', # 毎日深夜0時に実行
class: 'MyHogeTaskJob' # my_hoge_taskジョブで実行するJobクラスを指定
}
}
end
good_jobでは、
cron 定期的なスケジュールに沿って実行されるジョブ。cronはギリシャ語で'時間'
one_off 一度だけ実行されるジョブ
retryable ジョブの実行が失敗した場合に自動的にリトライするジョブ
priority ジョブに優先順位をつけて自動的にリトライするジョブ
queue ジョブを特定のキューに配置して異なる処理順序などで実行するジョブ
このような種類のジョブを実行することができます。今回は「毎晩深夜0時に実行されるジョブ」
を実装したかったのでcronジョブ
を設定しました。
cron: '0 0 * * *'
については、
-
0
分: 毎時0分に実行 -
0
時: 毎日0時(つまり、夜中の12時)に実行 -
*
日: 月のすべての日に実行 -
*
月: 年のすべての月に実行 -
*
曜日: 週のすべての曜日に実行
ということを意味しています。これで定期でジョブを実行するように設定できました。
実際にジョブを実装する
app/jobs/my_hoge_task_job.rbに最低限のジョブを実装します。
こちらのファイルではどのバッチ処理ファイルを行うかを定義して、詳細はバッチ処理専用のファイルに持たせることが一般的らしい
app/jobs/my_hoge_task_job.rb
class MyHogeTaskJob < ApplicationJob
queue_as :default #Active Jobフレームワークにおいて、ジョブがどのキューに入れられるかを指定
def perform
MyHogeTaskBatch.new.call #詳細を持たせたMyHogeTaskBatchをnewして、callメソッドを実行
end
end
app/batches/my_hoge_task_batche.rbのcallメソッドに詳細な処理内容を実装。
class MyHogeTaskBatch
def call
実行したい処理
end
end
テストコードについて
spec/jobs/my_hoge_task_job_spec.rbにモックを使用したテストを書きました
モックを使用したテストの実装について、過去に自分がまとめた記事
MyHogeTaskJobの動作確認は
「MyHogeTaskBatchのの詳細を隔離したまま、batchという代替品にcallメソッドが届くかどうかの確認をする」という方法でテストをしています。
spec/jobs/my_hoge_task_job_spec.rb
require 'rails_helper'
RSpec.describe MyHogeTaskJob do
it 'MyHogeTaskBatchのインスタンスが生成されcallメソッドが呼び出される' do
batch = MyHogeTaskBatch.new
allow(MyHogeTaskBatch).to receive(:new).and_return(batch)
allow(batch).to receive(:call)
described_class.perform_now
expect(batch).to have_received(:call)
end
end
もちろん、詳細なテストもspec/batches/my_hoge_taks_batch_spec.rbに書きます。
require 'rails_helper'
RSpec.describe MyHogeTaskBatch do
describe '#call' do
subject { described_class.new.call }
詳細な内容を確かめるテスト
end
end
まとめ
以上のような手順でgood_jobを使用してcronジョブを実装できました。
初学者の書いた記事なので、間違っている場合があります。そのときはご指摘していただけると大変助かります