activejob 4.2.11.3 → 5.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activejob might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +88 -54
- data/MIT-LICENSE +1 -1
- data/README.md +5 -5
- data/lib/active_job.rb +2 -1
- data/lib/active_job/arguments.rb +38 -19
- data/lib/active_job/async_job.rb +77 -0
- data/lib/active_job/base.rb +3 -1
- data/lib/active_job/callbacks.rb +2 -2
- data/lib/active_job/core.rb +42 -5
- data/lib/active_job/enqueuing.rb +5 -0
- data/lib/active_job/gem_version.rb +4 -4
- data/lib/active_job/logging.rb +17 -3
- data/lib/active_job/queue_adapter.rb +44 -16
- data/lib/active_job/queue_adapters.rb +86 -0
- data/lib/active_job/queue_adapters/async_adapter.rb +23 -0
- data/lib/active_job/queue_adapters/backburner_adapter.rb +6 -8
- data/lib/active_job/queue_adapters/delayed_job_adapter.rb +9 -7
- data/lib/active_job/queue_adapters/inline_adapter.rb +5 -7
- data/lib/active_job/queue_adapters/qu_adapter.rb +11 -9
- data/lib/active_job/queue_adapters/que_adapter.rb +9 -7
- data/lib/active_job/queue_adapters/queue_classic_adapter.rb +22 -20
- data/lib/active_job/queue_adapters/resque_adapter.rb +8 -10
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +15 -17
- data/lib/active_job/queue_adapters/sneakers_adapter.rb +11 -11
- data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +5 -7
- data/lib/active_job/queue_adapters/test_adapter.rb +25 -16
- data/lib/active_job/queue_name.rb +1 -1
- data/lib/active_job/queue_priority.rb +44 -0
- data/lib/active_job/test_helper.rb +144 -46
- data/lib/rails/generators/job/job_generator.rb +1 -2
- data/lib/rails/generators/job/templates/job.rb +1 -1
- metadata +15 -10
@@ -13,15 +13,13 @@ module ActiveJob
|
|
13
13
|
#
|
14
14
|
# Rails.application.config.active_job.queue_adapter = :backburner
|
15
15
|
class BackburnerAdapter
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
16
|
+
def enqueue(job) #:nodoc:
|
17
|
+
Backburner::Worker.enqueue JobWrapper, [ job.serialize ], queue: job.queue_name
|
18
|
+
end
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
20
|
+
def enqueue_at(job, timestamp) #:nodoc:
|
21
|
+
delay = timestamp - Time.current.to_f
|
22
|
+
Backburner::Worker.enqueue JobWrapper, [ job.serialize ], queue: job.queue_name, delay: delay
|
25
23
|
end
|
26
24
|
|
27
25
|
class JobWrapper #:nodoc:
|
@@ -13,14 +13,16 @@ module ActiveJob
|
|
13
13
|
#
|
14
14
|
# Rails.application.config.active_job.queue_adapter = :delayed_job
|
15
15
|
class DelayedJobAdapter
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def enqueue(job) #:nodoc:
|
17
|
+
delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, priority: job.priority)
|
18
|
+
job.provider_job_id = delayed_job.id
|
19
|
+
delayed_job
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
def enqueue_at(job, timestamp) #:nodoc:
|
23
|
+
delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, priority: job.priority, run_at: Time.at(timestamp))
|
24
|
+
job.provider_job_id = delayed_job.id
|
25
|
+
delayed_job
|
24
26
|
end
|
25
27
|
|
26
28
|
class JobWrapper #:nodoc:
|
@@ -9,14 +9,12 @@ module ActiveJob
|
|
9
9
|
#
|
10
10
|
# Rails.application.config.active_job.queue_adapter = :inline
|
11
11
|
class InlineAdapter
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
12
|
+
def enqueue(job) #:nodoc:
|
13
|
+
Base.execute(job.serialize)
|
14
|
+
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
end
|
16
|
+
def enqueue_at(*) #:nodoc:
|
17
|
+
raise NotImplementedError, "Use a queueing backend to enqueue jobs in the future. Read more at http://guides.rubyonrails.org/active_job_basics.html"
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|
@@ -16,16 +16,18 @@ module ActiveJob
|
|
16
16
|
#
|
17
17
|
# Rails.application.config.active_job.queue_adapter = :qu
|
18
18
|
class QuAdapter
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
def enqueue(job, *args) #:nodoc:
|
20
|
+
qu_job = Qu::Payload.new(klass: JobWrapper, args: [job.serialize]).tap do |payload|
|
21
|
+
payload.instance_variable_set(:@queue, job.queue_name)
|
22
|
+
end.push
|
23
|
+
|
24
|
+
# qu_job can be nil depending on the configured backend
|
25
|
+
job.provider_job_id = qu_job.id unless qu_job.nil?
|
26
|
+
qu_job
|
27
|
+
end
|
25
28
|
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
+
def enqueue_at(job, timestamp, *args) #:nodoc:
|
30
|
+
raise NotImplementedError, "This queueing backend does not support scheduling jobs. To see what features are supported go to http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html"
|
29
31
|
end
|
30
32
|
|
31
33
|
class JobWrapper < Qu::Job #:nodoc:
|
@@ -15,14 +15,16 @@ module ActiveJob
|
|
15
15
|
#
|
16
16
|
# Rails.application.config.active_job.queue_adapter = :que
|
17
17
|
class QueAdapter
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
def enqueue(job) #:nodoc:
|
19
|
+
que_job = JobWrapper.enqueue job.serialize, priority: job.priority
|
20
|
+
job.provider_job_id = que_job.attrs["job_id"]
|
21
|
+
que_job
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
def enqueue_at(job, timestamp) #:nodoc:
|
25
|
+
que_job = JobWrapper.enqueue job.serialize, priority: job.priority, run_at: Time.at(timestamp)
|
26
|
+
job.provider_job_id = que_job.attrs["job_id"]
|
27
|
+
que_job
|
26
28
|
end
|
27
29
|
|
28
30
|
class JobWrapper < Que::Job #:nodoc:
|
@@ -17,29 +17,31 @@ module ActiveJob
|
|
17
17
|
#
|
18
18
|
# Rails.application.config.active_job.queue_adapter = :queue_classic
|
19
19
|
class QueueClassicAdapter
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
def enqueue(job) #:nodoc:
|
21
|
+
qc_job = build_queue(job.queue_name).enqueue("#{JobWrapper.name}.perform", job.serialize)
|
22
|
+
job.provider_job_id = qc_job["id"] if qc_job.is_a?(Hash)
|
23
|
+
qc_job
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
32
|
-
queue.enqueue_at(timestamp, "#{JobWrapper.name}.perform", job.serialize)
|
26
|
+
def enqueue_at(job, timestamp) #:nodoc:
|
27
|
+
queue = build_queue(job.queue_name)
|
28
|
+
unless queue.respond_to?(:enqueue_at)
|
29
|
+
raise NotImplementedError, 'To be able to schedule jobs with queue_classic ' \
|
30
|
+
'the QC::Queue needs to respond to `enqueue_at(timestamp, method, *args)`. ' \
|
31
|
+
'You can implement this yourself or you can use the queue_classic-later gem.'
|
33
32
|
end
|
33
|
+
qc_job = queue.enqueue_at(timestamp, "#{JobWrapper.name}.perform", job.serialize)
|
34
|
+
job.provider_job_id = qc_job["id"] if qc_job.is_a?(Hash)
|
35
|
+
qc_job
|
36
|
+
end
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
38
|
+
# Builds a <tt>QC::Queue</tt> object to schedule jobs on.
|
39
|
+
#
|
40
|
+
# If you have a custom <tt>QC::Queue</tt> subclass you'll need to subclass
|
41
|
+
# <tt>ActiveJob::QueueAdapters::QueueClassicAdapter</tt> and override the
|
42
|
+
# <tt>build_queue</tt> method.
|
43
|
+
def build_queue(queue_name)
|
44
|
+
QC::Queue.new(queue_name)
|
43
45
|
end
|
44
46
|
|
45
47
|
class JobWrapper #:nodoc:
|
@@ -26,18 +26,16 @@ module ActiveJob
|
|
26
26
|
#
|
27
27
|
# Rails.application.config.active_job.queue_adapter = :resque
|
28
28
|
class ResqueAdapter
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
29
|
+
def enqueue(job) #:nodoc:
|
30
|
+
Resque.enqueue_to job.queue_name, JobWrapper, job.serialize
|
31
|
+
end
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
Resque.enqueue_at_with_queue job.queue_name, timestamp, JobWrapper, job.serialize
|
33
|
+
def enqueue_at(job, timestamp) #:nodoc:
|
34
|
+
unless Resque.respond_to?(:enqueue_at_with_queue)
|
35
|
+
raise NotImplementedError, "To be able to schedule jobs with Resque you need the " \
|
36
|
+
"resque-scheduler gem. Please add it to your Gemfile and run bundle install"
|
40
37
|
end
|
38
|
+
Resque.enqueue_at_with_queue job.queue_name, timestamp, JobWrapper, job.serialize
|
41
39
|
end
|
42
40
|
|
43
41
|
class JobWrapper #:nodoc:
|
@@ -15,24 +15,22 @@ module ActiveJob
|
|
15
15
|
#
|
16
16
|
# Rails.application.config.active_job.queue_adapter = :sidekiq
|
17
17
|
class SidekiqAdapter
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
18
|
+
def enqueue(job) #:nodoc:
|
19
|
+
#Sidekiq::Client does not support symbols as keys
|
20
|
+
job.provider_job_id = Sidekiq::Client.push \
|
21
|
+
'class' => JobWrapper,
|
22
|
+
'wrapped' => job.class.to_s,
|
23
|
+
'queue' => job.queue_name,
|
24
|
+
'args' => [ job.serialize ]
|
25
|
+
end
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
27
|
+
def enqueue_at(job, timestamp) #:nodoc:
|
28
|
+
job.provider_job_id = Sidekiq::Client.push \
|
29
|
+
'class' => JobWrapper,
|
30
|
+
'wrapped' => job.class.to_s,
|
31
|
+
'queue' => job.queue_name,
|
32
|
+
'args' => [ job.serialize ],
|
33
|
+
'at' => timestamp
|
36
34
|
end
|
37
35
|
|
38
36
|
class JobWrapper #:nodoc:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'sneakers'
|
2
|
-
require '
|
2
|
+
require 'monitor'
|
3
3
|
|
4
4
|
module ActiveJob
|
5
5
|
module QueueAdapters
|
@@ -16,19 +16,19 @@ module ActiveJob
|
|
16
16
|
#
|
17
17
|
# Rails.application.config.active_job.queue_adapter = :sneakers
|
18
18
|
class SneakersAdapter
|
19
|
-
|
19
|
+
def initialize
|
20
|
+
@monitor = Monitor.new
|
21
|
+
end
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
JobWrapper.enqueue ActiveSupport::JSON.encode(job.serialize)
|
26
|
-
end
|
23
|
+
def enqueue(job) #:nodoc:
|
24
|
+
@monitor.synchronize do
|
25
|
+
JobWrapper.from_queue job.queue_name
|
26
|
+
JobWrapper.enqueue ActiveSupport::JSON.encode(job.serialize)
|
27
27
|
end
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
end
|
30
|
+
def enqueue_at(job, timestamp) #:nodoc:
|
31
|
+
raise NotImplementedError, "This queueing backend does not support scheduling jobs. To see what features are supported go to http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html"
|
32
32
|
end
|
33
33
|
|
34
34
|
class JobWrapper #:nodoc:
|
@@ -18,14 +18,12 @@ module ActiveJob
|
|
18
18
|
#
|
19
19
|
# Rails.application.config.active_job.queue_adapter = :sucker_punch
|
20
20
|
class SuckerPunchAdapter
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
21
|
+
def enqueue(job) #:nodoc:
|
22
|
+
JobWrapper.new.async.perform job.serialize
|
23
|
+
end
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
end
|
25
|
+
def enqueue_at(job, timestamp) #:nodoc:
|
26
|
+
raise NotImplementedError, "This queueing backend does not support scheduling jobs. To see what features are supported go to http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html"
|
29
27
|
end
|
30
28
|
|
31
29
|
class JobWrapper #:nodoc:
|
@@ -10,15 +10,9 @@ module ActiveJob
|
|
10
10
|
#
|
11
11
|
# Rails.application.config.active_job.queue_adapter = :test
|
12
12
|
class TestAdapter
|
13
|
-
|
14
|
-
attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs)
|
13
|
+
attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter)
|
15
14
|
attr_writer(:enqueued_jobs, :performed_jobs)
|
16
15
|
|
17
|
-
def initialize
|
18
|
-
self.perform_enqueued_jobs = false
|
19
|
-
self.perform_enqueued_at_jobs = false
|
20
|
-
end
|
21
|
-
|
22
16
|
# Provides a store of all the enqueued jobs with the TestAdapter so you can check them.
|
23
17
|
def enqueued_jobs
|
24
18
|
@enqueued_jobs ||= []
|
@@ -30,22 +24,37 @@ module ActiveJob
|
|
30
24
|
end
|
31
25
|
|
32
26
|
def enqueue(job) #:nodoc:
|
33
|
-
if
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
enqueued_jobs << {job: job.class, args: job.serialize['arguments'], queue: job.queue_name}
|
38
|
-
end
|
27
|
+
return if filtered?(job)
|
28
|
+
|
29
|
+
job_data = job_to_hash(job)
|
30
|
+
enqueue_or_perform(perform_enqueued_jobs, job, job_data)
|
39
31
|
end
|
40
32
|
|
41
33
|
def enqueue_at(job, timestamp) #:nodoc:
|
42
|
-
if
|
43
|
-
|
34
|
+
return if filtered?(job)
|
35
|
+
|
36
|
+
job_data = job_to_hash(job, at: timestamp)
|
37
|
+
enqueue_or_perform(perform_enqueued_at_jobs, job, job_data)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def job_to_hash(job, extras = {})
|
43
|
+
{ job: job.class, args: job.serialize.fetch('arguments'), queue: job.queue_name }.merge!(extras)
|
44
|
+
end
|
45
|
+
|
46
|
+
def enqueue_or_perform(perform, job, job_data)
|
47
|
+
if perform
|
48
|
+
performed_jobs << job_data
|
44
49
|
Base.execute job.serialize
|
45
50
|
else
|
46
|
-
enqueued_jobs <<
|
51
|
+
enqueued_jobs << job_data
|
47
52
|
end
|
48
53
|
end
|
54
|
+
|
55
|
+
def filtered?(job)
|
56
|
+
filter && !Array(filter).include?(job.class)
|
57
|
+
end
|
49
58
|
end
|
50
59
|
end
|
51
60
|
end
|
@@ -39,7 +39,7 @@ module ActiveJob
|
|
39
39
|
self.queue_name_delimiter = '_' # set default delimiter to '_'
|
40
40
|
end
|
41
41
|
|
42
|
-
# Returns the name of the queue the job will be run on
|
42
|
+
# Returns the name of the queue the job will be run on.
|
43
43
|
def queue_name
|
44
44
|
if @queue_name.is_a?(Proc)
|
45
45
|
@queue_name = self.class.queue_name_from_part(instance_exec(&@queue_name))
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ActiveJob
|
2
|
+
module QueuePriority
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
# Includes the ability to override the default queue priority.
|
6
|
+
module ClassMethods
|
7
|
+
mattr_accessor(:default_priority)
|
8
|
+
|
9
|
+
# Specifies the priority of the queue to create the job with.
|
10
|
+
#
|
11
|
+
# class PublishToFeedJob < ActiveJob::Base
|
12
|
+
# queue_with_priority 50
|
13
|
+
#
|
14
|
+
# def perform(post)
|
15
|
+
# post.to_feed!
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# Specify either an argument or a block.
|
20
|
+
def queue_with_priority(priority=nil, &block)
|
21
|
+
if block_given?
|
22
|
+
self.priority = block
|
23
|
+
else
|
24
|
+
self.priority = priority
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
included do
|
30
|
+
class_attribute :priority, instance_accessor: false
|
31
|
+
|
32
|
+
self.priority = default_priority
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the priority that the job will be created with
|
36
|
+
def priority
|
37
|
+
if @priority.is_a?(Proc)
|
38
|
+
@priority = instance_exec(&@priority)
|
39
|
+
end
|
40
|
+
@priority
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'active_support/core_ext/class/subclasses'
|
1
2
|
require 'active_support/core_ext/hash/keys'
|
2
3
|
|
3
4
|
module ActiveJob
|
@@ -6,17 +7,28 @@ module ActiveJob
|
|
6
7
|
extend ActiveSupport::Concern
|
7
8
|
|
8
9
|
included do
|
9
|
-
def before_setup
|
10
|
-
|
11
|
-
|
10
|
+
def before_setup # :nodoc:
|
11
|
+
test_adapter = ActiveJob::QueueAdapters::TestAdapter.new
|
12
|
+
|
13
|
+
@old_queue_adapters = (ActiveJob::Base.subclasses << ActiveJob::Base).select do |klass|
|
14
|
+
# only override explicitly set adapters, a quirk of `class_attribute`
|
15
|
+
klass.singleton_class.public_instance_methods(false).include?(:_queue_adapter)
|
16
|
+
end.map do |klass|
|
17
|
+
[klass, klass.queue_adapter].tap do
|
18
|
+
klass.queue_adapter = test_adapter
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
12
22
|
clear_enqueued_jobs
|
13
23
|
clear_performed_jobs
|
14
24
|
super
|
15
25
|
end
|
16
26
|
|
17
|
-
def after_teardown
|
27
|
+
def after_teardown # :nodoc:
|
18
28
|
super
|
19
|
-
|
29
|
+
@old_queue_adapters.each do |(klass, adapter)|
|
30
|
+
klass.queue_adapter = adapter
|
31
|
+
end
|
20
32
|
end
|
21
33
|
|
22
34
|
# Asserts that the number of enqueued jobs matches the given number.
|
@@ -42,16 +54,24 @@ module ActiveJob
|
|
42
54
|
# HelloJob.perform_later('rafael')
|
43
55
|
# end
|
44
56
|
# end
|
45
|
-
|
57
|
+
#
|
58
|
+
# The number of times a specific job is enqueued can be asserted.
|
59
|
+
#
|
60
|
+
# def test_logging_job
|
61
|
+
# assert_enqueued_jobs 2, only: LoggingJob do
|
62
|
+
# LoggingJob.perform_later
|
63
|
+
# HelloJob.perform_later('jeremy')
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
def assert_enqueued_jobs(number, only: nil)
|
46
67
|
if block_given?
|
47
|
-
original_count =
|
68
|
+
original_count = enqueued_jobs_size(only: only)
|
48
69
|
yield
|
49
|
-
new_count =
|
50
|
-
assert_equal number, new_count - original_count,
|
51
|
-
"#{number} jobs expected, but #{new_count - original_count} were enqueued"
|
70
|
+
new_count = enqueued_jobs_size(only: only)
|
71
|
+
assert_equal number, new_count - original_count, "#{number} jobs expected, but #{new_count - original_count} were enqueued"
|
52
72
|
else
|
53
|
-
|
54
|
-
assert_equal number,
|
73
|
+
actual_count = enqueued_jobs_size(only: only)
|
74
|
+
assert_equal number, actual_count, "#{number} jobs expected, but #{actual_count} were enqueued"
|
55
75
|
end
|
56
76
|
end
|
57
77
|
|
@@ -71,11 +91,19 @@ module ActiveJob
|
|
71
91
|
# end
|
72
92
|
# end
|
73
93
|
#
|
94
|
+
# It can be asserted that no jobs of a specific kind are enqueued:
|
95
|
+
#
|
96
|
+
# def test_no_logging
|
97
|
+
# assert_no_enqueued_jobs only: LoggingJob do
|
98
|
+
# HelloJob.perform_later('jeremy')
|
99
|
+
# end
|
100
|
+
# end
|
101
|
+
#
|
74
102
|
# Note: This assertion is simply a shortcut for:
|
75
103
|
#
|
76
104
|
# assert_enqueued_jobs 0, &block
|
77
|
-
def assert_no_enqueued_jobs(&block)
|
78
|
-
assert_enqueued_jobs 0, &block
|
105
|
+
def assert_no_enqueued_jobs(only: nil, &block)
|
106
|
+
assert_enqueued_jobs 0, only: only, &block
|
79
107
|
end
|
80
108
|
|
81
109
|
# Asserts that the number of performed jobs matches the given number.
|
@@ -109,10 +137,32 @@ module ActiveJob
|
|
109
137
|
# HelloJob.perform_later('sean')
|
110
138
|
# end
|
111
139
|
# end
|
112
|
-
|
140
|
+
#
|
141
|
+
# The block form supports filtering. If the :only option is specified,
|
142
|
+
# then only the listed job(s) will be performed.
|
143
|
+
#
|
144
|
+
# def test_hello_job
|
145
|
+
# assert_performed_jobs 1, only: HelloJob do
|
146
|
+
# HelloJob.perform_later('jeremy')
|
147
|
+
# LoggingJob.perform_later
|
148
|
+
# end
|
149
|
+
# end
|
150
|
+
#
|
151
|
+
# An array may also be specified, to support testing multiple jobs.
|
152
|
+
#
|
153
|
+
# def test_hello_and_logging_jobs
|
154
|
+
# assert_nothing_raised do
|
155
|
+
# assert_performed_jobs 2, only: [HelloJob, LoggingJob] do
|
156
|
+
# HelloJob.perform_later('jeremy')
|
157
|
+
# LoggingJob.perform_later('stewie')
|
158
|
+
# RescueJob.perform_later('david')
|
159
|
+
# end
|
160
|
+
# end
|
161
|
+
# end
|
162
|
+
def assert_performed_jobs(number, only: nil)
|
113
163
|
if block_given?
|
114
164
|
original_count = performed_jobs.size
|
115
|
-
perform_enqueued_jobs { yield }
|
165
|
+
perform_enqueued_jobs(only: only) { yield }
|
116
166
|
new_count = performed_jobs.size
|
117
167
|
assert_equal number, new_count - original_count,
|
118
168
|
"#{number} jobs expected, but #{new_count - original_count} were performed"
|
@@ -141,11 +191,33 @@ module ActiveJob
|
|
141
191
|
# end
|
142
192
|
# end
|
143
193
|
#
|
194
|
+
# The block form supports filtering. If the :only option is specified,
|
195
|
+
# then only the listed job(s) will be performed.
|
196
|
+
#
|
197
|
+
# def test_hello_job
|
198
|
+
# assert_performed_jobs 1, only: HelloJob do
|
199
|
+
# HelloJob.perform_later('jeremy')
|
200
|
+
# LoggingJob.perform_later
|
201
|
+
# end
|
202
|
+
# end
|
203
|
+
#
|
204
|
+
# An array may also be specified, to support testing multiple jobs.
|
205
|
+
#
|
206
|
+
# def test_hello_and_logging_jobs
|
207
|
+
# assert_nothing_raised do
|
208
|
+
# assert_performed_jobs 2, only: [HelloJob, LoggingJob] do
|
209
|
+
# HelloJob.perform_later('jeremy')
|
210
|
+
# LoggingJob.perform_later('stewie')
|
211
|
+
# RescueJob.perform_later('david')
|
212
|
+
# end
|
213
|
+
# end
|
214
|
+
# end
|
215
|
+
#
|
144
216
|
# Note: This assertion is simply a shortcut for:
|
145
217
|
#
|
146
218
|
# assert_performed_jobs 0, &block
|
147
|
-
def assert_no_performed_jobs(&block)
|
148
|
-
assert_performed_jobs 0, &block
|
219
|
+
def assert_no_performed_jobs(only: nil, &block)
|
220
|
+
assert_performed_jobs 0, only: only, &block
|
149
221
|
end
|
150
222
|
|
151
223
|
# Asserts that the job passed in the block has been enqueued with the given arguments.
|
@@ -154,19 +226,22 @@ module ActiveJob
|
|
154
226
|
# assert_enqueued_with(job: MyJob, args: [1,2,3], queue: 'low') do
|
155
227
|
# MyJob.perform_later(1,2,3)
|
156
228
|
# end
|
229
|
+
#
|
230
|
+
# assert_enqueued_with(job: MyJob, at: Date.tomorrow.noon) do
|
231
|
+
# MyJob.set(wait_until: Date.tomorrow.noon).perform_later
|
232
|
+
# end
|
157
233
|
# end
|
158
|
-
def assert_enqueued_with(args = {}
|
159
|
-
|
160
|
-
clear_enqueued_jobs
|
234
|
+
def assert_enqueued_with(args = {})
|
235
|
+
original_enqueued_jobs_count = enqueued_jobs.count
|
161
236
|
args.assert_valid_keys(:job, :args, :at, :queue)
|
162
237
|
serialized_args = serialize_args_for_assertion(args)
|
163
238
|
yield
|
164
|
-
|
239
|
+
in_block_jobs = enqueued_jobs.drop(original_enqueued_jobs_count)
|
240
|
+
matching_job = in_block_jobs.find do |job|
|
165
241
|
serialized_args.all? { |key, value| value == job[key] }
|
166
242
|
end
|
167
243
|
assert matching_job, "No enqueued job found with #{args}"
|
168
|
-
|
169
|
-
queue_adapter.enqueued_jobs = original_enqueued_jobs + enqueued_jobs
|
244
|
+
instantiate_job(matching_job)
|
170
245
|
end
|
171
246
|
|
172
247
|
# Asserts that the job passed in the block has been performed with the given arguments.
|
@@ -175,30 +250,39 @@ module ActiveJob
|
|
175
250
|
# assert_performed_with(job: MyJob, args: [1,2,3], queue: 'high') do
|
176
251
|
# MyJob.perform_later(1,2,3)
|
177
252
|
# end
|
253
|
+
#
|
254
|
+
# assert_performed_with(job: MyJob, at: Date.tomorrow.noon) do
|
255
|
+
# MyJob.set(wait_until: Date.tomorrow.noon).perform_later
|
256
|
+
# end
|
178
257
|
# end
|
179
|
-
def assert_performed_with(args = {}
|
180
|
-
|
181
|
-
clear_performed_jobs
|
258
|
+
def assert_performed_with(args = {})
|
259
|
+
original_performed_jobs_count = performed_jobs.count
|
182
260
|
args.assert_valid_keys(:job, :args, :at, :queue)
|
183
261
|
serialized_args = serialize_args_for_assertion(args)
|
184
262
|
perform_enqueued_jobs { yield }
|
185
|
-
|
263
|
+
in_block_jobs = performed_jobs.drop(original_performed_jobs_count)
|
264
|
+
matching_job = in_block_jobs.find do |job|
|
186
265
|
serialized_args.all? { |key, value| value == job[key] }
|
187
266
|
end
|
188
267
|
assert matching_job, "No performed job found with #{args}"
|
189
|
-
|
190
|
-
queue_adapter.performed_jobs = original_performed_jobs + performed_jobs
|
268
|
+
instantiate_job(matching_job)
|
191
269
|
end
|
192
270
|
|
193
|
-
def perform_enqueued_jobs
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
271
|
+
def perform_enqueued_jobs(only: nil)
|
272
|
+
old_perform_enqueued_jobs = queue_adapter.perform_enqueued_jobs
|
273
|
+
old_perform_enqueued_at_jobs = queue_adapter.perform_enqueued_at_jobs
|
274
|
+
old_filter = queue_adapter.filter
|
275
|
+
|
276
|
+
begin
|
277
|
+
queue_adapter.perform_enqueued_jobs = true
|
278
|
+
queue_adapter.perform_enqueued_at_jobs = true
|
279
|
+
queue_adapter.filter = only
|
280
|
+
yield
|
281
|
+
ensure
|
282
|
+
queue_adapter.perform_enqueued_jobs = old_perform_enqueued_jobs
|
283
|
+
queue_adapter.perform_enqueued_at_jobs = old_perform_enqueued_at_jobs
|
284
|
+
queue_adapter.filter = old_filter
|
285
|
+
end
|
202
286
|
end
|
203
287
|
|
204
288
|
def queue_adapter
|
@@ -210,20 +294,34 @@ module ActiveJob
|
|
210
294
|
to: :queue_adapter
|
211
295
|
|
212
296
|
private
|
213
|
-
def clear_enqueued_jobs
|
297
|
+
def clear_enqueued_jobs # :nodoc:
|
214
298
|
enqueued_jobs.clear
|
215
299
|
end
|
216
300
|
|
217
|
-
def clear_performed_jobs
|
301
|
+
def clear_performed_jobs # :nodoc:
|
218
302
|
performed_jobs.clear
|
219
303
|
end
|
220
304
|
|
221
|
-
def
|
222
|
-
|
223
|
-
|
224
|
-
|
305
|
+
def enqueued_jobs_size(only: nil) # :nodoc:
|
306
|
+
if only
|
307
|
+
enqueued_jobs.count { |job| Array(only).include?(job.fetch(:job)) }
|
308
|
+
else
|
309
|
+
enqueued_jobs.count
|
225
310
|
end
|
226
|
-
|
311
|
+
end
|
312
|
+
|
313
|
+
def serialize_args_for_assertion(args) # :nodoc:
|
314
|
+
args.dup.tap do |serialized_args|
|
315
|
+
serialized_args[:args] = ActiveJob::Arguments.serialize(serialized_args[:args]) if serialized_args[:args]
|
316
|
+
serialized_args[:at] = serialized_args[:at].to_f if serialized_args[:at]
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
def instantiate_job(payload) # :nodoc:
|
321
|
+
job = payload[:job].new(*payload[:args])
|
322
|
+
job.scheduled_at = Time.at(payload[:at]) if payload.key?(:at)
|
323
|
+
job.queue_name = payload[:queue]
|
324
|
+
job
|
227
325
|
end
|
228
326
|
end
|
229
327
|
end
|