Ruby rails: jobs
ActiveJob
is an abstraction of jobs that can be placed in a queue and run asynchronously.
Rails ships with an in-memory queue (jobs lost on reset), but includes adapters for several queue systems.
NOTE:
The official guide for jobs is really good, consult that first. https://guides.rubyonrails.org/active_job_basics.html
Documentation
official guide https://guides.rubyonrails.org/active_job_basics.html official testing guide https://guides.rubyonrails.org/testing.html#testing-jobs API docs https://api.rubyonrails.org/classes/ActiveJob.html API Queue Adapters https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html
Locations
app/jobs/{jobname}_job.rb
job itself test/jobs/{jobname}_job_test.rb
job test
Commandline
rails g job guests_cleanup # -> GuestsCleanupJob
Example
# app/jobs/user_cleanup_job.rb class UserCleanupJob < ApplicationJob queue_as :default def perform(*users) # ... end endEnqueue a job
UserCleanupJob.perform_later(user1, user2) UsersCleanupJob.set(wait_until: Date.tomorrow.noon).perform_later(user) UsersCleanupJob.set(wait: 1.week).perform_later(user)
Queue Backend
Rails ships with non-persistent in-memory queue.
You probably want to use an adapter for a backend persists application restarts.Common Backends
sidekiq resque sneakers sucker punch queue classic delayed job Set Backend
Globally
# config/application.rb module YourApp class Application < Rails::Application config.active_job.queue_adapter = :sidekiq # <--- end endPer-Job
class GuestsCleanupJob < ApplicationJob self.queue_adapter = :resque # <--- end
Syntax
Enqueueing Jobs
MyJob.perform_now(arg1: "foo") # enqueue job MyJob.new(arg1: "foo").enqueue # enqueue job MyJob.perform_later(arg1: "foo") # perform synchronously where calledPriority
You can set the default priority, queue etc on the class.
or you can override it when you enqueue it.TODO:
expand on this.
MyJob.set(priority: 50).perform_later(arg1: "foo")Arguments/DataTypes
Datatypes used in arguments must be serializable in order to be used in jobs.
ActiveJob
supports the following types, and also exposes an interface
so you can manage serialization/deserialization of custom types.Natively supported DataTypes
Basic types (NilClass, String, Integer, Float, BigDecimal, TrueClass, FalseClass) Symbol Date Time DateTime ActiveSupport::TimeWithZone ActiveSupport::Duration Hash (Keys should be of String or Symbol type) ActiveSupport::HashWithIndifferentAccess ArrayCustom Serializer for your DataTypes
# define serializer (where?) class MoneySerializer < ActiveJob::Serializers::ObjectSerializer # Checks if an argument should be serialized by this serializer. def serialize?(argument) argument.is_a? Money end def serialize(money) super("amount" => money.amount, "currency" => money.currency) end def deserialize(hash) Money.new(hash["amount"], hash["currency"]) end endEnable serializer for activejobs
# config/application.rb module Project class Application < Rails::Application config.active_job.custom_serializers << MoneySerializer end endExceptions
You can assign behaviour to exceptions encountered during the execution of a job.
You may want to log/reraise, discard, or retry on specific exceptions.class GuestsCleanupJob < ApplicationJob queue_as :default # retry/discard retry_on MyRetryError discard_on MyCancelError # handle exception rescue_from(ActiveRecord::RecordNotFound) do |exception| # ... end def perform # ... end endCallbacks
before_enqueue around_enqueue after_enqueue before_perform around_perform after_performQueue Contents
ActiveJob::Base.queue_adapter.enqueued_jobs # jobs in the queue
Extensions
ruby job-iteration