activejob 5.0.7.2 → 5.1.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 +24 -221
- data/MIT-LICENSE +1 -1
- data/README.md +1 -1
- data/lib/active_job.rb +5 -5
- data/lib/active_job/arguments.rb +7 -19
- data/lib/active_job/base.rb +11 -9
- data/lib/active_job/callbacks.rb +3 -3
- data/lib/active_job/configured_job.rb +1 -1
- data/lib/active_job/core.rb +14 -9
- data/lib/active_job/enqueuing.rb +7 -32
- data/lib/active_job/exceptions.rb +122 -0
- data/lib/active_job/execution.rb +5 -2
- data/lib/active_job/gem_version.rb +3 -3
- data/lib/active_job/logging.rb +56 -56
- data/lib/active_job/queue_adapter.rb +14 -26
- data/lib/active_job/queue_adapters.rb +2 -2
- data/lib/active_job/queue_adapters/async_adapter.rb +4 -4
- data/lib/active_job/queue_adapters/backburner_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/delayed_job_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/qu_adapter.rb +3 -3
- data/lib/active_job/queue_adapters/que_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/queue_classic_adapter.rb +4 -4
- data/lib/active_job/queue_adapters/resque_adapter.rb +5 -5
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +11 -11
- data/lib/active_job/queue_adapters/sneakers_adapter.rb +3 -3
- data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +3 -3
- data/lib/active_job/queue_adapters/test_adapter.rb +13 -17
- data/lib/active_job/queue_name.rb +2 -3
- data/lib/active_job/queue_priority.rb +1 -2
- data/lib/active_job/railtie.rb +4 -4
- data/lib/active_job/test_case.rb +1 -1
- data/lib/active_job/test_helper.rb +78 -39
- data/lib/active_job/version.rb +1 -1
- data/lib/rails/generators/job/job_generator.rb +12 -12
- data/lib/rails/generators/job/templates/application_job.rb +5 -0
- metadata +9 -7
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "qu"
|
2
2
|
|
3
3
|
module ActiveJob
|
4
4
|
module QueueAdapters
|
@@ -20,7 +20,7 @@ module ActiveJob
|
|
20
20
|
qu_job = Qu::Payload.new(klass: JobWrapper, args: [job.serialize]).tap do |payload|
|
21
21
|
payload.instance_variable_set(:@queue, job.queue_name)
|
22
22
|
end.push
|
23
|
-
|
23
|
+
|
24
24
|
# qu_job can be nil depending on the configured backend
|
25
25
|
job.provider_job_id = qu_job.id unless qu_job.nil?
|
26
26
|
qu_job
|
@@ -32,7 +32,7 @@ module ActiveJob
|
|
32
32
|
|
33
33
|
class JobWrapper < Qu::Job #:nodoc:
|
34
34
|
def initialize(job_data)
|
35
|
-
@job_data
|
35
|
+
@job_data = job_data
|
36
36
|
end
|
37
37
|
|
38
38
|
def perform
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "queue_classic"
|
2
2
|
|
3
3
|
module ActiveJob
|
4
4
|
module QueueAdapters
|
@@ -26,9 +26,9 @@ module ActiveJob
|
|
26
26
|
def enqueue_at(job, timestamp) #:nodoc:
|
27
27
|
queue = build_queue(job.queue_name)
|
28
28
|
unless queue.respond_to?(:enqueue_at)
|
29
|
-
raise NotImplementedError,
|
30
|
-
|
31
|
-
|
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."
|
32
32
|
end
|
33
33
|
qc_job = queue.enqueue_at(timestamp, "#{JobWrapper.name}.perform", job.serialize)
|
34
34
|
job.provider_job_id = qc_job["id"] if qc_job.is_a?(Hash)
|
@@ -1,12 +1,12 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "resque"
|
2
|
+
require "active_support/core_ext/enumerable"
|
3
|
+
require "active_support/core_ext/array/access"
|
4
4
|
|
5
5
|
begin
|
6
|
-
require
|
6
|
+
require "resque-scheduler"
|
7
7
|
rescue LoadError
|
8
8
|
begin
|
9
|
-
require
|
9
|
+
require "resque_scheduler"
|
10
10
|
rescue LoadError
|
11
11
|
false
|
12
12
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "sidekiq"
|
2
2
|
|
3
3
|
module ActiveJob
|
4
4
|
module QueueAdapters
|
@@ -18,26 +18,26 @@ module ActiveJob
|
|
18
18
|
def enqueue(job) #:nodoc:
|
19
19
|
#Sidekiq::Client does not support symbols as keys
|
20
20
|
job.provider_job_id = Sidekiq::Client.push \
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
"class" => JobWrapper,
|
22
|
+
"wrapped" => job.class.to_s,
|
23
|
+
"queue" => job.queue_name,
|
24
|
+
"args" => [ job.serialize ]
|
25
25
|
end
|
26
26
|
|
27
27
|
def enqueue_at(job, timestamp) #:nodoc:
|
28
28
|
job.provider_job_id = Sidekiq::Client.push \
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
"class" => JobWrapper,
|
30
|
+
"wrapped" => job.class.to_s,
|
31
|
+
"queue" => job.queue_name,
|
32
|
+
"args" => [ job.serialize ],
|
33
|
+
"at" => timestamp
|
34
34
|
end
|
35
35
|
|
36
36
|
class JobWrapper #:nodoc:
|
37
37
|
include Sidekiq::Worker
|
38
38
|
|
39
39
|
def perform(job_data)
|
40
|
-
Base.execute job_data.merge(
|
40
|
+
Base.execute job_data.merge("provider_job_id" => jid)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "sneakers"
|
2
|
+
require "monitor"
|
3
3
|
|
4
4
|
module ActiveJob
|
5
5
|
module QueueAdapters
|
@@ -33,7 +33,7 @@ module ActiveJob
|
|
33
33
|
|
34
34
|
class JobWrapper #:nodoc:
|
35
35
|
include Sneakers::Worker
|
36
|
-
from_queue
|
36
|
+
from_queue "default"
|
37
37
|
|
38
38
|
def work(msg)
|
39
39
|
job_data = ActiveSupport::JSON.decode(msg)
|
@@ -1,11 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require "sucker_punch"
|
2
2
|
|
3
3
|
module ActiveJob
|
4
4
|
module QueueAdapters
|
5
5
|
# == Sucker Punch adapter for Active Job
|
6
6
|
#
|
7
7
|
# Sucker Punch is a single-process Ruby asynchronous processing library.
|
8
|
-
# This reduces the cost of
|
8
|
+
# This reduces the cost of hosting on a service like Heroku along
|
9
9
|
# with the memory footprint of having to maintain additional jobs if
|
10
10
|
# hosting on a dedicated server. All queues can run within a
|
11
11
|
# single application (eg. Rails, Sinatra, etc.) process.
|
@@ -31,7 +31,7 @@ module ActiveJob
|
|
31
31
|
delay = timestamp - Time.current.to_f
|
32
32
|
JobWrapper.perform_in delay, job.serialize
|
33
33
|
else
|
34
|
-
raise NotImplementedError,
|
34
|
+
raise NotImplementedError, "sucker_punch 1.0 does not support `enqueued_at`. Please upgrade to version ~> 2.0.0 to enable this behavior."
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -24,37 +24,33 @@ module ActiveJob
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def enqueue(job) #:nodoc:
|
27
|
-
return if filtered?(job)
|
28
|
-
|
29
27
|
job_data = job_to_hash(job)
|
30
28
|
enqueue_or_perform(perform_enqueued_jobs, job, job_data)
|
31
29
|
end
|
32
30
|
|
33
31
|
def enqueue_at(job, timestamp) #:nodoc:
|
34
|
-
return if filtered?(job)
|
35
|
-
|
36
32
|
job_data = job_to_hash(job, at: timestamp)
|
37
33
|
enqueue_or_perform(perform_enqueued_at_jobs, job, job_data)
|
38
34
|
end
|
39
35
|
|
40
36
|
private
|
41
37
|
|
42
|
-
|
43
|
-
|
44
|
-
|
38
|
+
def job_to_hash(job, extras = {})
|
39
|
+
{ job: job.class, args: job.serialize.fetch("arguments"), queue: job.queue_name }.merge!(extras)
|
40
|
+
end
|
45
41
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
42
|
+
def enqueue_or_perform(perform, job, job_data)
|
43
|
+
if !perform || filtered?(job)
|
44
|
+
enqueued_jobs << job_data
|
45
|
+
else
|
46
|
+
performed_jobs << job_data
|
47
|
+
Base.execute job.serialize
|
48
|
+
end
|
52
49
|
end
|
53
|
-
end
|
54
50
|
|
55
|
-
|
56
|
-
|
57
|
-
|
51
|
+
def filtered?(job)
|
52
|
+
filter && !Array(filter).include?(job.class)
|
53
|
+
end
|
58
54
|
end
|
59
55
|
end
|
60
56
|
end
|
@@ -16,7 +16,7 @@ module ActiveJob
|
|
16
16
|
# post.to_feed!
|
17
17
|
# end
|
18
18
|
# end
|
19
|
-
def queue_as(part_name=nil, &block)
|
19
|
+
def queue_as(part_name = nil, &block)
|
20
20
|
if block_given?
|
21
21
|
self.queue_name = block
|
22
22
|
else
|
@@ -36,7 +36,7 @@ module ActiveJob
|
|
36
36
|
class_attribute :queue_name_delimiter, instance_accessor: false
|
37
37
|
|
38
38
|
self.queue_name = default_queue_name
|
39
|
-
self.queue_name_delimiter =
|
39
|
+
self.queue_name_delimiter = "_" # set default delimiter to '_'
|
40
40
|
end
|
41
41
|
|
42
42
|
# Returns the name of the queue the job will be run on.
|
@@ -46,6 +46,5 @@ module ActiveJob
|
|
46
46
|
end
|
47
47
|
@queue_name
|
48
48
|
end
|
49
|
-
|
50
49
|
end
|
51
50
|
end
|
@@ -17,7 +17,7 @@ module ActiveJob
|
|
17
17
|
# end
|
18
18
|
#
|
19
19
|
# Specify either an argument or a block.
|
20
|
-
def queue_with_priority(priority=nil, &block)
|
20
|
+
def queue_with_priority(priority = nil, &block)
|
21
21
|
if block_given?
|
22
22
|
self.priority = block
|
23
23
|
else
|
@@ -39,6 +39,5 @@ module ActiveJob
|
|
39
39
|
end
|
40
40
|
@priority
|
41
41
|
end
|
42
|
-
|
43
42
|
end
|
44
43
|
end
|
data/lib/active_job/railtie.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "global_id/railtie"
|
2
|
+
require "active_job"
|
3
3
|
|
4
4
|
module ActiveJob
|
5
5
|
# = Active Job Railtie
|
6
6
|
class Railtie < Rails::Railtie # :nodoc:
|
7
7
|
config.active_job = ActiveSupport::OrderedOptions.new
|
8
8
|
|
9
|
-
initializer
|
9
|
+
initializer "active_job.logger" do
|
10
10
|
ActiveSupport.on_load(:active_job) { self.logger = ::Rails.logger }
|
11
11
|
end
|
12
12
|
|
@@ -15,7 +15,7 @@ module ActiveJob
|
|
15
15
|
options.queue_adapter ||= :async
|
16
16
|
|
17
17
|
ActiveSupport.on_load(:active_job) do
|
18
|
-
options.each { |k,v| send("#{k}=", v) }
|
18
|
+
options.each { |k, v| send("#{k}=", v) }
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
data/lib/active_job/test_case.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "active_support/core_ext/class/subclasses"
|
2
|
+
require "active_support/core_ext/hash/keys"
|
3
3
|
|
4
4
|
module ActiveJob
|
5
5
|
# Provides helper methods for testing Active Job
|
@@ -8,16 +8,35 @@ module ActiveJob
|
|
8
8
|
:performed_jobs, :performed_jobs=,
|
9
9
|
to: :queue_adapter
|
10
10
|
|
11
|
+
module TestQueueAdapter
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
included do
|
15
|
+
class_attribute :_test_adapter, instance_accessor: false, instance_predicate: false
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
def queue_adapter
|
20
|
+
self._test_adapter.nil? ? super : self._test_adapter
|
21
|
+
end
|
22
|
+
|
23
|
+
def disable_test_adapter
|
24
|
+
self._test_adapter = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def enable_test_adapter(test_adapter)
|
28
|
+
self._test_adapter = test_adapter
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
ActiveJob::Base.include(TestQueueAdapter)
|
34
|
+
|
11
35
|
def before_setup # :nodoc:
|
12
36
|
test_adapter = queue_adapter_for_test
|
13
37
|
|
14
|
-
|
15
|
-
|
16
|
-
klass.singleton_class.public_instance_methods(false).include?(:_queue_adapter)
|
17
|
-
end.map do |klass|
|
18
|
-
[klass, klass.queue_adapter].tap do
|
19
|
-
klass.queue_adapter = test_adapter
|
20
|
-
end
|
38
|
+
queue_adapter_changed_jobs.each do |klass|
|
39
|
+
klass.enable_test_adapter(test_adapter)
|
21
40
|
end
|
22
41
|
|
23
42
|
clear_enqueued_jobs
|
@@ -27,9 +46,8 @@ module ActiveJob
|
|
27
46
|
|
28
47
|
def after_teardown # :nodoc:
|
29
48
|
super
|
30
|
-
|
31
|
-
|
32
|
-
end
|
49
|
+
|
50
|
+
queue_adapter_changed_jobs.each { |klass| klass.disable_test_adapter }
|
33
51
|
end
|
34
52
|
|
35
53
|
# Specifies the queue adapter to use with all active job test helpers.
|
@@ -55,7 +73,7 @@ module ActiveJob
|
|
55
73
|
# assert_enqueued_jobs 2
|
56
74
|
# end
|
57
75
|
#
|
58
|
-
# If a block is passed, that block
|
76
|
+
# If a block is passed, that block will cause the specified number of
|
59
77
|
# jobs to be enqueued.
|
60
78
|
#
|
61
79
|
# def test_jobs_again
|
@@ -77,14 +95,23 @@ module ActiveJob
|
|
77
95
|
# HelloJob.perform_later('jeremy')
|
78
96
|
# end
|
79
97
|
# end
|
80
|
-
|
98
|
+
#
|
99
|
+
# The number of times a job is enqueued to a specific queue can also be asserted.
|
100
|
+
#
|
101
|
+
# def test_logging_job
|
102
|
+
# assert_enqueued_jobs 2, queue: 'default' do
|
103
|
+
# LoggingJob.perform_later
|
104
|
+
# HelloJob.perform_later('elfassy')
|
105
|
+
# end
|
106
|
+
# end
|
107
|
+
def assert_enqueued_jobs(number, only: nil, queue: nil)
|
81
108
|
if block_given?
|
82
|
-
original_count = enqueued_jobs_size(only: only)
|
109
|
+
original_count = enqueued_jobs_size(only: only, queue: queue)
|
83
110
|
yield
|
84
|
-
new_count = enqueued_jobs_size(only: only)
|
111
|
+
new_count = enqueued_jobs_size(only: only, queue: queue)
|
85
112
|
assert_equal number, new_count - original_count, "#{number} jobs expected, but #{new_count - original_count} were enqueued"
|
86
113
|
else
|
87
|
-
actual_count = enqueued_jobs_size(only: only)
|
114
|
+
actual_count = enqueued_jobs_size(only: only, queue: queue)
|
88
115
|
assert_equal number, actual_count, "#{number} jobs expected, but #{actual_count} were enqueued"
|
89
116
|
end
|
90
117
|
end
|
@@ -232,16 +259,16 @@ module ActiveJob
|
|
232
259
|
# MyJob.set(wait_until: Date.tomorrow.noon).perform_later
|
233
260
|
# end
|
234
261
|
# end
|
235
|
-
def assert_enqueued_with(args
|
262
|
+
def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil)
|
236
263
|
original_enqueued_jobs_count = enqueued_jobs.count
|
237
|
-
|
238
|
-
serialized_args = serialize_args_for_assertion(
|
264
|
+
expected = { job: job, args: args, at: at, queue: queue }.compact
|
265
|
+
serialized_args = serialize_args_for_assertion(expected)
|
239
266
|
yield
|
240
267
|
in_block_jobs = enqueued_jobs.drop(original_enqueued_jobs_count)
|
241
|
-
matching_job = in_block_jobs.find do |
|
242
|
-
serialized_args.all? { |key, value| value ==
|
268
|
+
matching_job = in_block_jobs.find do |in_block_job|
|
269
|
+
serialized_args.all? { |key, value| value == in_block_job[key] }
|
243
270
|
end
|
244
|
-
assert matching_job, "No enqueued job found with #{
|
271
|
+
assert matching_job, "No enqueued job found with #{expected}"
|
245
272
|
instantiate_job(matching_job)
|
246
273
|
end
|
247
274
|
|
@@ -256,16 +283,16 @@ module ActiveJob
|
|
256
283
|
# MyJob.set(wait_until: Date.tomorrow.noon).perform_later
|
257
284
|
# end
|
258
285
|
# end
|
259
|
-
def assert_performed_with(args
|
286
|
+
def assert_performed_with(job: nil, args: nil, at: nil, queue: nil)
|
260
287
|
original_performed_jobs_count = performed_jobs.count
|
261
|
-
|
262
|
-
serialized_args = serialize_args_for_assertion(
|
288
|
+
expected = { job: job, args: args, at: at, queue: queue }.compact
|
289
|
+
serialized_args = serialize_args_for_assertion(expected)
|
263
290
|
perform_enqueued_jobs { yield }
|
264
291
|
in_block_jobs = performed_jobs.drop(original_performed_jobs_count)
|
265
|
-
matching_job = in_block_jobs.find do |
|
266
|
-
serialized_args.all? { |key, value| value ==
|
292
|
+
matching_job = in_block_jobs.find do |in_block_job|
|
293
|
+
serialized_args.all? { |key, value| value == in_block_job[key] }
|
267
294
|
end
|
268
|
-
assert matching_job, "No performed job found with #{
|
295
|
+
assert matching_job, "No performed job found with #{expected}"
|
269
296
|
instantiate_job(matching_job)
|
270
297
|
end
|
271
298
|
|
@@ -284,7 +311,7 @@ module ActiveJob
|
|
284
311
|
# def test_perform_enqueued_jobs_with_only
|
285
312
|
# perform_enqueued_jobs(only: MyJob) do
|
286
313
|
# MyJob.perform_later(1, 2, 3) # will be performed
|
287
|
-
# HelloJob.perform_later(1, 2, 3) # will not be
|
314
|
+
# HelloJob.perform_later(1, 2, 3) # will not be performed
|
288
315
|
# end
|
289
316
|
# assert_performed_jobs 1
|
290
317
|
# end
|
@@ -315,34 +342,46 @@ module ActiveJob
|
|
315
342
|
end
|
316
343
|
|
317
344
|
private
|
318
|
-
def clear_enqueued_jobs
|
345
|
+
def clear_enqueued_jobs
|
319
346
|
enqueued_jobs.clear
|
320
347
|
end
|
321
348
|
|
322
|
-
def clear_performed_jobs
|
349
|
+
def clear_performed_jobs
|
323
350
|
performed_jobs.clear
|
324
351
|
end
|
325
352
|
|
326
|
-
def enqueued_jobs_size(only: nil
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
353
|
+
def enqueued_jobs_size(only: nil, queue: nil)
|
354
|
+
enqueued_jobs.count do |job|
|
355
|
+
job_class = job.fetch(:job)
|
356
|
+
if only
|
357
|
+
next false unless Array(only).include?(job_class)
|
358
|
+
end
|
359
|
+
if queue
|
360
|
+
next false unless queue.to_s == job.fetch(:queue, job_class.queue_name)
|
361
|
+
end
|
362
|
+
true
|
331
363
|
end
|
332
364
|
end
|
333
365
|
|
334
|
-
def serialize_args_for_assertion(args)
|
366
|
+
def serialize_args_for_assertion(args)
|
335
367
|
args.dup.tap do |serialized_args|
|
336
368
|
serialized_args[:args] = ActiveJob::Arguments.serialize(serialized_args[:args]) if serialized_args[:args]
|
337
369
|
serialized_args[:at] = serialized_args[:at].to_f if serialized_args[:at]
|
338
370
|
end
|
339
371
|
end
|
340
372
|
|
341
|
-
def instantiate_job(payload)
|
373
|
+
def instantiate_job(payload)
|
342
374
|
job = payload[:job].new(*payload[:args])
|
343
375
|
job.scheduled_at = Time.at(payload[:at]) if payload.key?(:at)
|
344
376
|
job.queue_name = payload[:queue]
|
345
377
|
job
|
346
378
|
end
|
379
|
+
|
380
|
+
def queue_adapter_changed_jobs
|
381
|
+
(ActiveJob::Base.descendants << ActiveJob::Base).select do |klass|
|
382
|
+
# only override explicitly set adapters, a quirk of `class_attribute`
|
383
|
+
klass.singleton_class.public_instance_methods(false).include?(:_queue_adapter)
|
384
|
+
end
|
385
|
+
end
|
347
386
|
end
|
348
387
|
end
|