Skip to content

Commit

Permalink
Enqueue all jobs with an :each at the start, but refrain from enqueui…
Browse files Browse the repository at this point in the history
…ng all jobs every time a job completes.
  • Loading branch information
Tom Scott committed Oct 5, 2019
1 parent 27735c3 commit b2000d8
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 18 deletions.
47 changes: 36 additions & 11 deletions lib/active_job/scheduler/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
2 changes: 1 addition & 1 deletion lib/active_job/scheduler/job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def repeat(
#
# @private
def enqueue_job
event.enqueue
event.enqueue(*arguments)
end

# Whether this job is scheduled.
Expand Down
2 changes: 1 addition & 1 deletion lib/active_job/scheduler/schedule.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def find_by_name(name)
#
# @return [Array<ActiveJob::Base>]
def start
events.map(&:enqueue)
events.map(&:schedule)
end

private
Expand Down
10 changes: 5 additions & 5 deletions test/active_job/scheduler/event_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit b2000d8

Please sign in to comment.