nanohablog

技術ブログ

Delayed :: Cron :: Job の使用方法

公式 https://github.com/codez/delayed_cron_job#changing-the-schedule

Delayed :: Cron :: Job とは

Rails用のGemでDelayed :: Job の拡張機能であり、ジョブを実行式をcron形式で設定できます。

インストール

  1. Gemfile に以下の行を追記します。

    gem delayed_cron_job

  2. bundle インストールを実行します。

    $ bundle

  3. migration ファイルを作成、実行します。 ※ delayed_job_active_recordを使用している場合、delayed_jobs テーブルに cron カラムが追加されます。

    $ rails generate delayed_job:cron $ rails db:migrate

使用方法

以下の様に Delayed::Job クラスを呼び出し、引数に実行したいJob、実行時間を記載します。

Delayed::Job.enqueue(MyRepeatedJob.new, cron: '15 */6 * * 1-5')

若しくは ActivieJob を使用して以下の様に記述します。

MyJob.set(cron: '*/5 * * * *').perform_later

スケジューリング

通常、アプリケーションをデプロイするタイミングで、全てのJobの設定が必要になります。これを以下の様なスーパークラスを作成する事で簡単に行うことができます。

Custom CronJob superclass

app/jobs/cron_job.rb:

# Default configuration in `app/jobs/application_job.rb`, or subclass
# ActiveJob::Base .
class CronJob < ApplicationJob

  class_attribute :cron_expression

  class << self

    def schedule
      set(cron: cron_expression).perform_later unless scheduled?
    end

    def remove
      delayed_job.destroy if scheduled?
    end

    def scheduled?
      delayed_job.present?
    end

    def delayed_job
      Delayed::Job
        .where('handler LIKE ?', "%job_class: #{name}%")
        .first
    end

  end
end

CronJobから継承するジョブの例

app/jobs/noon_job.rb:

# Note that it inherits from `CronJob`
class NoonJob < CronJob
  # set the (default) cron expression
  self.cron_expression = '0 12 * * *'

  # will enqueue the mailing delivery job
  def perform
    UserMailer.daily_notice(User.first).deliver_later
  end
end

スケジューリングトリガー

一番初めにJobをDBに登録してスケジューリングを行う必要があります。手動で行いたくない場合、以下のようなJobクラスを作成してrails db:* クラスにフックする事が可能です。

lib/tasks/jobs.rake:

namespace :db do
  desc 'Schedule all cron jobs'
  task :schedule_jobs => :environment do
    # Need to load all jobs definitions in order to find subclasses
    glob = Rails.root.join('app', 'jobs', '**', '*_job.rb')
    Dir.glob(glob).each { |file| require file }
    CronJob.subclasses.each(&:schedule)
  end
end

# invoke schedule_jobs automatically after every migration and schema load.
%w(db:migrate db:schema:load).each do |task|
  Rake::Task[task].enhance do
    Rake::Task['db:schedule_jobs'].invoke
  end
end

以下のコマンドを実行する事でJobがDBに登録されて、設定時刻に実行されます。

rails db:migrate rails db:schema:load rails db:schedule_job