Ruby rails: jobs: Difference between revisions
(→Syntax) |
|||
(2 intermediate revisions by the same user not shown) | |||
Line 113: | Line 113: | ||
= Syntax = | = Syntax = | ||
<blockquote> | <blockquote> | ||
== Enqueueing Jobs == | |||
<blockquote> | |||
<syntaxhighlight lang="ruby"> | |||
MyJob.perform_now(arg1: "foo") # enqueue job | |||
MyJob.new(arg1: "foo").enqueue # enqueue job | |||
MyJob.perform_later(arg1: "foo") # perform synchronously where called | |||
</syntaxhighlight> | |||
</blockquote><!-- Enqueueing Jobs --> | |||
== Priority == | |||
<blockquote> | |||
You can set the default priority, queue etc on the class.<br> | |||
or you can override it when you enqueue it. | |||
Set default priority | |||
<syntaxhighlight lang="ruby"> | |||
class MyJob < ApplicationJob | |||
queue_with_priority 50 | |||
def perform(message) | |||
puts("hi there") | |||
end | |||
end | |||
</syntaxhighlight> | |||
Override priority at enqueue time | |||
<syntaxhighlight lang="ruby"> | |||
MyJob | |||
.set(priority: 50) | |||
.perform_later("hi there") | |||
</syntaxhighlight> | |||
</blockquote><!-- Priority --> | |||
== Arguments/DataTypes == | == Arguments/DataTypes == | ||
<blockquote> | <blockquote> | ||
Line 147: | Line 180: | ||
argument.is_a? Money | argument.is_a? Money | ||
end | end | ||
def serialize(money) | def serialize(money) | ||
super("amount" => money.amount, "currency" => money.currency) | super("amount" => money.amount, "currency" => money.currency) | ||
end | end | ||
def deserialize(hash) | def deserialize(hash) | ||
Money.new(hash["amount"], hash["currency"]) | Money.new(hash["amount"], hash["currency"]) | ||
Line 180: | Line 213: | ||
class GuestsCleanupJob < ApplicationJob | class GuestsCleanupJob < ApplicationJob | ||
queue_as :default | queue_as :default | ||
# retry/discard | # retry/discard | ||
retry_on MyRetryError | retry_on MyRetryError | ||
Line 189: | Line 222: | ||
# ... | # ... | ||
end | end | ||
def perform | def perform | ||
# ... | # ... |
Latest revision as of 20:43, 19 September 2021
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.Set default priority
class MyJob < ApplicationJob queue_with_priority 50 def perform(message) puts("hi there") end endOverride priority at enqueue time
MyJob .set(priority: 50) .perform_later("hi there")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