February 28, 2023
This blog is part of our Rails 7 series.
Rails 7.1 adds ActiveJob.perform_all_later
to enqueue multiple jobs at once.
This method accepts an array of job instances. Just like Active Record bulk
methods, perform_all_later
doesn't run any callbacks.
For example, if we want to send a welcome email to multiple users, we can do this:
welcome_email_jobs = users.map do |user|
WelcomeEmailJob.new(user)
end
ActiveJob.perform_all_later(welcome_email_jobs)
The benefit of doing it this way rather than looping through the user records
and using perform_later
is that perform_all_later
cuts down on the number of
round-trips to the queue datastore. That means reducing Redis round trip latency
if the queuing backend is Sidekiq. Whereas if we're using a queuing backend like
GoodJob, which is backed by Postgres,
perform_all_later
will enqueue all the jobs using a single INSERT statement
which is more performant.
Please note that if the queuing backend doesn't support bulk enqueuing,
perform_all_later
will fallback to enqueuing each job individually.
Active Job is designed to abstract away the differences between different job processing libraries and to provide a unified interface. It is made possible using adapters.
The popular queuing backend Sidekiq already has a
push_bulk method.
Hence, the author of this pull request has made
changes
to the Sidekiq adapter so that perform_all_later
uses the push_bulk
method
from Sidekiq.
Recently, GoodJob has also added support for bulk enqueuing in this pull request.
Practically, ActiveJob.perform_all_later
is only useful if we want to push
thousands of jobs at once. For a smaller number of jobs, the performance
benefits will not be significant.
Please check out this pull request for more details.
If this blog was helpful, check out our full blog archive.