From b2000d89f666d0158dd6e1631ec8ffe723c9a268 Mon Sep 17 00:00:00 2001 From: Tom Scott Date: Sat, 5 Oct 2019 18:43:00 -0400 Subject: [PATCH] Enqueue all jobs with an :each at the start, but refrain from enqueuing all jobs every time a job completes. --- lib/active_job/scheduler/event.rb | 47 +++++++++++++++++++------ lib/active_job/scheduler/job.rb | 2 +- lib/active_job/scheduler/schedule.rb | 2 +- test/active_job/scheduler/event_test.rb | 10 +++--- 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/lib/active_job/scheduler/event.rb b/lib/active_job/scheduler/event.rb index e946278..dfd1544 100644 --- a/lib/active_job/scheduler/event.rb +++ b/lib/active_job/scheduler/event.rb @@ -39,27 +39,31 @@ def job_class raise NotDefinedError, job_class_name end - # Job object that has been delayed by the interval. - # - # @return [ActiveJob::Base] + # All jobs to be enqueued. def jobs - return Array.wrap(job_class.set(wait: interval.to_duration)) if single? + return Array.wrap(job) if single? @each.call.map do |item| args = arguments + [item] - [job_class.set(wait: interval.to_duration), args] + [job, args] end end + # Job object that has been delayed by the interval. + # + # @return [ActiveJob::Base] + def job + job_class.set(wait: interval.to_duration) + end + # Whether to call `@each` and iterate def single? @each.blank? end - # Enqueue the job for a later time. - # - # @return [ActiveJob::Base] - def enqueue + # Enqueue all jobs specified by `:each` in the settings, or a + # single job as the start of the schedule. + def schedule if job_class < ActiveJob::Base enqueue_jobs elsif job_class < ActionMailer::Base @@ -69,21 +73,42 @@ def enqueue end end + # Enqueue the job for a later time. + def enqueue(*job_args) + args = arguments + job_args + + if job_class < ActiveJob::Base + job.perform_later(*args) + elsif job_class < ActionMailer::Base + mail(*args).deliver_later(wait: interval.to_duration) + else + raise TypeError, "#{job_class} is not supported by #{self}" + end + end + private + # @private def enqueue_jobs jobs.each { |job, args| job.perform_later(*args) } end + # @private def enqueue_mails return job_class.send(@mail, *arguments) if single? @each.call.each do |item| args = arguments + [item] - job_class.send(@mail, *args) - .deliver_later(wait: interval.to_duration) + mail = mailer(*args) + + mail.deliver_later(wait: interval.to_duration) end end + + # @private + def mailer(*args) + job_class.send(@mail, *args) + end end end end diff --git a/lib/active_job/scheduler/job.rb b/lib/active_job/scheduler/job.rb index ee1c3d3..0f999e2 100644 --- a/lib/active_job/scheduler/job.rb +++ b/lib/active_job/scheduler/job.rb @@ -67,7 +67,7 @@ def repeat( # # @private def enqueue_job - event.enqueue + event.enqueue(*arguments) end # Whether this job is scheduled. diff --git a/lib/active_job/scheduler/schedule.rb b/lib/active_job/scheduler/schedule.rb index 0e65759..a6e9e0f 100644 --- a/lib/active_job/scheduler/schedule.rb +++ b/lib/active_job/scheduler/schedule.rb @@ -41,7 +41,7 @@ def find_by_name(name) # # @return [Array] def start - events.map(&:enqueue) + events.map(&:schedule) end private diff --git a/test/active_job/scheduler/event_test.rb b/test/active_job/scheduler/event_test.rb index 14ae7e4..52c87f5 100644 --- a/test/active_job/scheduler/event_test.rb +++ b/test/active_job/scheduler/event_test.rb @@ -24,7 +24,7 @@ class EventTest < ActiveJob::TestCase end test 'enqueues job for later' do - assert_kind_of Array, @event.enqueue + assert_kind_of FooBarJob, @event.enqueue end test 'throw error when job class not defined' do @@ -39,15 +39,15 @@ class EventTest < ActiveJob::TestCase assert_raises(TypeError) { bogus.enqueue } end - test 'enqueue multiple jobs' do + test 'schedule jobs' do assert_enqueued_jobs 2, only: MultiJob do - Scheduler.events.find_by_name('MultiJob').enqueue + Scheduler.events.find_by_name('MultiJob').schedule end end - test 'enqueue multiple mails' do + test 'schedule mails' do assert_enqueued_jobs 2, only: ActionMailer::DeliveryJob do - Scheduler.events.find_by_name('MultiMailer').enqueue + Scheduler.events.find_by_name('MultiMailer').schedule end end end