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.
Follow @bigbinary on X. Check out our full blog archive.