Skip to content

Commit 554e71a

Browse files
[RF DOCS] Add documentation for perform_all_later to Active Job Basics guide [ci-skip] (rails#51004)
Add documentation related to perform_all_later for bulk enqueuing jobs. Co-authored-by: Carlos Antonio da Silva <[email protected]>
1 parent 5cc11f7 commit 554e71a

File tree

1 file changed

+103
-2
lines changed

1 file changed

+103
-2
lines changed

guides/source/active_job_basics.md

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ runs jobs with an in-process thread pool. Jobs will run asynchronously, but any
3939
jobs in the queue will be dropped upon restart.
4040

4141

42-
Creating a Job
43-
--------------
42+
Create and Enqueue Jobs
43+
-----------------------
4444

4545
This section will provide a step-by-step guide to creating a job and enqueuing it.
4646

@@ -127,6 +127,10 @@ That's it!
127127
[`perform_later`]: https://api.rubyonrails.org/classes/ActiveJob/Enqueuing/ClassMethods.html#method-i-perform_later
128128
[`set`]: https://api.rubyonrails.org/classes/ActiveJob/Core/ClassMethods.html#method-i-set
129129

130+
### Enqueue Jobs in Bulk
131+
132+
You can enqueue multiple jobs at once using [`perform_all_later`](https://api.rubyonrails.org/classes/ActiveJob.html#method-c-perform_all_later). For more details see [Bulk Enqueuing](#bulk-enqueuing).
133+
130134
Job Execution
131135
-------------
132136

@@ -406,6 +410,103 @@ end
406410
[`around_perform`]: https://api.rubyonrails.org/classes/ActiveJob/Callbacks/ClassMethods.html#method-i-around_perform
407411
[`after_perform`]: https://api.rubyonrails.org/classes/ActiveJob/Callbacks/ClassMethods.html#method-i-after_perform
408412

413+
Please note that when enqueuing jobs in bulk using `perform_all_later`,
414+
callbacks such as `around_enqueue` will not be triggered on the individual jobs.
415+
See [Bulk Enqueuing Callbacks](#bulk-enqueue-callbacks).
416+
417+
Bulk Enqueuing
418+
--------------
419+
420+
You can enqueue multiple jobs at once using
421+
[`perform_all_later`](https://api.rubyonrails.org/classes/ActiveJob.html#method-c-perform_all_later).
422+
Bulk enqueuing reduces the number of round trips to the queue data store (like
423+
Redis or a database), making it a more performant operation than enqueuing the
424+
same jobs individually.
425+
426+
`perform_all_later` is a top-level API on Active Job. It accepts instantiated
427+
jobs as arguments (note that this is different from `perform_later`).
428+
`perform_all_later` does call `perform` under the hood. The arguments passed to
429+
`new` will be passed on to `perform` when it's eventually called.
430+
431+
Here is an example calling `perform_all_later` with `GuestCleanupJob` instances:
432+
433+
```ruby
434+
# Create jobs to pass to `perform_all_later`.
435+
# The arguments to `new` are passed on to `perform`
436+
guest_cleanup_jobs = Guest.all.map { |guest| GuestsCleanupJob.new(guest) }
437+
438+
# Will enqueue a separate job for each instance of `GuestCleanupJob`
439+
ActiveJob.perform_all_later(guest_cleanup_jobs)
440+
441+
# Can also use `set` method to configure options before bulk enqueuing jobs.
442+
guest_cleanup_jobs = Guest.all.map { |guest| GuestsCleanupJob.new(guest).set(wait: 1.day) }
443+
444+
ActiveJob.perform_all_later(guest_cleanup_jobs)
445+
```
446+
447+
`perform_all_later` logs the number of jobs successfully enqueued, for example
448+
if `Guest.all.map` above resulted in 3 `guest_cleanup_jobs`, it would log
449+
`Enqueued 3 jobs to Async (3 GuestsCleanupJob)` (assuming all were enqueued).
450+
451+
The return value of `perform_all_later` is `nil`. Note that this is different
452+
from `perform_later`, which returns the instance of the queued job class.
453+
454+
### Enqueue Multiple Active Job Classes
455+
456+
With `perform_all_later`, it's also possible to enqueue different Active Job
457+
class instances in the same call. For example:
458+
459+
```ruby
460+
class ExportDataJob < ApplicationJob
461+
def perform(*args)
462+
# Export data
463+
end
464+
end
465+
466+
class NotifyGuestsJob < ApplicationJob
467+
def perform(*guests)
468+
# Email guests
469+
end
470+
end
471+
472+
# Instantiate job instances
473+
cleanup_job = GuestsCleanupJob.new(guest)
474+
export_job = ExportDataJob.new(data)
475+
notify_job = NotifyGuestsJob.new(guest)
476+
477+
# Enqueues job instances from multiple classes at once
478+
ActiveJob.perform_all_later(cleanup_job, export_job, notify_job)
479+
```
480+
481+
### Bulk Enqueue Callbacks
482+
483+
When enqueuing jobs in bulk using `perform_all_later`, callbacks such as
484+
`around_enqueue` will not be triggered on the individual jobs. This behavior is
485+
in line with other Active Record bulk methods. Since callbacks run on individual
486+
jobs, they can't take advantage of the bulk nature of this method.
487+
488+
However, the `perform_all_later` method does fire an
489+
[`enqueue_all.active_job`](active_support_instrumentation.html#enqueue-all-active-job)
490+
event which you can subscribe to using `ActiveSupport::Notifications`.
491+
492+
The method
493+
[`successfully_enqueued?`](https://api.rubyonrails.org/classes/ActiveJob/Core.html#method-i-successfully_enqueued-3F)
494+
can be used to find out if a given job was successfully enqueued.
495+
496+
### Queue Backend Support
497+
498+
For `perform_all_later`, bulk enqueuing needs to be backed by the [queue
499+
backend](#backends).
500+
501+
For example, Sidekiq has a `push_bulk` method, which can push a large number of
502+
jobs to Redis and prevent the round trip network latency. GoodJob also supports
503+
bulk enqueuing with the `GoodJob::Bulk.enqueue` method. The new queue backend
504+
[`Solid Queue`](https://github.com/basecamp/solid_queue/pull/93) has added
505+
support for bulk enqueuing as well.
506+
507+
If the queue backend does *not* support bulk enqueuing, `perform_all_later` will
508+
enqueue jobs one by one.
509+
409510
Action Mailer
410511
------------
411512

0 commit comments

Comments
 (0)