ruk·si

🛤️ Ruby on Rails
Jobs

Updated at 2015-08-21 00:54

ActiveJob is a framework for declaring queued background processes. It's a common interface to use adapter for e.g. Delayed Job, Resque and Sidekiq. See QueueAdapters docs for the full list of supported adapters. If no adapter is defined, the job is instantly executed.

# Defining adapter, remember to add the adapter to your Gemfile.
# config/application.rb
module YourApp
  class Application < Rails::Application
    config.active_job.queue_adapter = :sidekiq      # adapter to use
    config.active_job.queue_name_prefix = Rails.env # custom prefix to queues
    config.active_job.queue_name_delimiter = '_'    # separator to use
  end
end

Creating jobs. Created jobs are placed to app/jobs. You can also just write them yourself.

rails g job guests_cleanup
rails g job guests_cleanup --queue urgent # assign to named queue
# app/jobs/guest_cleanup_job.rb
class GuestsCleanupJob < ActiveJob::Base
  queue_as :default

  def perform(*args)
    # ...
  end
end

Placing your jobs to a queue.

MyJob.perform_later(record) # queue and run as soon as possible
MyJob.set(wait_until: Date.tomorrow.noon).perform_later(record)
MyJob.set(wait: 1.week).perform_later(record)
MyJob.set(queue: :another_queue).perform_later(record)

You can use conditional queue selection.

class ProcessVideoJob < ActiveJob::Base
  queue_as do
    video = self.arguments.first
    if video.owner.premium?
      :premium_videojobs
    else
      :videojobs
    end
  end

  def perform(video)
    # ...
  end
end

Jobs have many callbacks you can utilize.

class GuestsCleanupJob < ActiveJob::Base
  queue_as :default

  # before_enqueue
  # around_enqueue
  # after_enqueue
  # before_perform
  # around_perform
  # after_perform

  before_enqueue do |job|
    # ...
  end

  around_perform do |job, block|
    # before perform
    block.call
    # after perform
  end

  def perform
    # ...
  end
end

GlobalID class references. If your class includes GlobalID::Identification, which is included by default to models, you can just pass instance to the job.

class TrashableCleanupJob < ActiveJob::Base
  def perform(trashable, depth)
    trashable.cleanup(depth)
  end
end

Remember to handle exceptions.

class GuestsCleanupJob < ActiveJob::Base
  queue_as :default

  rescue_from(ActiveRecord::RecordNotFound) do |exception|
    # ...
  end

  def perform
    # ...
  end
end

Sources