activejob 6.0.3.3 → 6.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +82 -149
- data/MIT-LICENSE +1 -1
- data/README.md +1 -3
- data/lib/active_job.rb +1 -1
- data/lib/active_job/base.rb +3 -0
- data/lib/active_job/callbacks.rb +44 -4
- data/lib/active_job/core.rb +3 -2
- data/lib/active_job/enqueuing.rb +3 -13
- data/lib/active_job/exceptions.rb +29 -20
- data/lib/active_job/execution.rb +9 -1
- data/lib/active_job/gem_version.rb +3 -3
- data/lib/active_job/instrumentation.rb +40 -0
- data/lib/active_job/log_subscriber.rb +140 -0
- data/lib/active_job/logging.rb +3 -132
- data/lib/active_job/queue_adapter.rb +3 -0
- data/lib/active_job/queue_adapters.rb +5 -1
- data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/test_adapter.rb +6 -2
- data/lib/active_job/queue_name.rb +2 -2
- data/lib/active_job/railtie.rb +4 -0
- data/lib/active_job/serializers.rb +4 -1
- data/lib/active_job/serializers/date_time_serializer.rb +1 -5
- data/lib/active_job/serializers/module_serializer.rb +20 -0
- data/lib/active_job/serializers/object_serializer.rb +1 -1
- data/lib/active_job/serializers/time_object_serializer.rb +13 -0
- data/lib/active_job/serializers/time_serializer.rb +1 -5
- data/lib/active_job/serializers/time_with_zone_serializer.rb +1 -5
- data/lib/active_job/test_helper.rb +81 -80
- metadata +15 -11
@@ -11,6 +11,9 @@ module ActiveJob
|
|
11
11
|
included do
|
12
12
|
class_attribute :_queue_adapter_name, instance_accessor: false, instance_predicate: false
|
13
13
|
class_attribute :_queue_adapter, instance_accessor: false, instance_predicate: false
|
14
|
+
|
15
|
+
delegate :queue_adapter, to: :class
|
16
|
+
|
14
17
|
self.queue_adapter = :async
|
15
18
|
end
|
16
19
|
|
@@ -72,7 +72,7 @@ module ActiveJob
|
|
72
72
|
# Yes: Allows the priority to be set on the job object, at the queue level or
|
73
73
|
# as default configuration option.
|
74
74
|
#
|
75
|
-
# No:
|
75
|
+
# No: The adapter does not allow the priority of jobs to be configured.
|
76
76
|
#
|
77
77
|
# N/A: The adapter does not support queuing, and therefore sorting them.
|
78
78
|
#
|
@@ -86,6 +86,8 @@ module ActiveJob
|
|
86
86
|
#
|
87
87
|
# Global: The adapter is configured that all jobs have a maximum run time.
|
88
88
|
#
|
89
|
+
# No: The adapter does not allow the timeout of jobs to be configured.
|
90
|
+
#
|
89
91
|
# N/A: This adapter does not run in a separate process, and therefore timeout
|
90
92
|
# is unsupported.
|
91
93
|
#
|
@@ -99,6 +101,8 @@ module ActiveJob
|
|
99
101
|
#
|
100
102
|
# Global: The adapter has a global number of retries.
|
101
103
|
#
|
104
|
+
# No: The adapter does not allow the number of retries to be configured.
|
105
|
+
#
|
102
106
|
# N/A: The adapter does not run in a separate process, and therefore doesn't
|
103
107
|
# support retries.
|
104
108
|
#
|
@@ -10,7 +10,7 @@ module ActiveJob
|
|
10
10
|
# This reduces the cost of hosting on a service like Heroku along
|
11
11
|
# with the memory footprint of having to maintain additional jobs if
|
12
12
|
# hosting on a dedicated server. All queues can run within a
|
13
|
-
# single application (
|
13
|
+
# single application (e.g. Rails, Sinatra, etc.) process.
|
14
14
|
#
|
15
15
|
# Read more about Sucker Punch {here}[https://github.com/brandonhilkert/sucker_punch].
|
16
16
|
#
|
@@ -12,7 +12,7 @@ module ActiveJob
|
|
12
12
|
#
|
13
13
|
# Rails.application.config.active_job.queue_adapter = :test
|
14
14
|
class TestAdapter
|
15
|
-
attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter, :reject, :queue)
|
15
|
+
attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter, :reject, :queue, :at)
|
16
16
|
attr_writer(:enqueued_jobs, :performed_jobs)
|
17
17
|
|
18
18
|
# Provides a store of all the enqueued jobs with the TestAdapter so you can check them.
|
@@ -54,7 +54,11 @@ module ActiveJob
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def filtered?(job)
|
57
|
-
filtered_queue?(job) || filtered_job_class?(job)
|
57
|
+
filtered_queue?(job) || filtered_job_class?(job) || filtered_time?(job)
|
58
|
+
end
|
59
|
+
|
60
|
+
def filtered_time?(job)
|
61
|
+
job.scheduled_at > at.to_f if at && job.scheduled_at
|
58
62
|
end
|
59
63
|
|
60
64
|
def filtered_queue?(job)
|
@@ -6,7 +6,6 @@ module ActiveJob
|
|
6
6
|
|
7
7
|
# Includes the ability to override the default queue name and prefix.
|
8
8
|
module ClassMethods
|
9
|
-
mattr_accessor :queue_name_prefix
|
10
9
|
mattr_accessor :default_queue_name, default: "default"
|
11
10
|
|
12
11
|
# Specifies the name of the queue to process the job on.
|
@@ -49,13 +48,14 @@ module ActiveJob
|
|
49
48
|
def queue_name_from_part(part_name) #:nodoc:
|
50
49
|
queue_name = part_name || default_queue_name
|
51
50
|
name_parts = [queue_name_prefix.presence, queue_name]
|
52
|
-
name_parts.compact.join(queue_name_delimiter)
|
51
|
+
-name_parts.compact.join(queue_name_delimiter)
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
56
55
|
included do
|
57
56
|
class_attribute :queue_name, instance_accessor: false, default: -> { self.class.default_queue_name }
|
58
57
|
class_attribute :queue_name_delimiter, instance_accessor: false, default: "_"
|
58
|
+
class_attribute :queue_name_prefix
|
59
59
|
end
|
60
60
|
|
61
61
|
# Returns the name of the queue the job will be run on.
|
data/lib/active_job/railtie.rb
CHANGED
@@ -34,6 +34,10 @@ module ActiveJob
|
|
34
34
|
ActiveSupport.on_load(:action_dispatch_integration_test) do
|
35
35
|
include ActiveJob::TestHelper
|
36
36
|
end
|
37
|
+
|
38
|
+
ActiveSupport.on_load(:active_record) do
|
39
|
+
self.destroy_association_async_job = ActiveRecord::DestroyAssociationAsyncJob
|
40
|
+
end
|
37
41
|
end
|
38
42
|
|
39
43
|
initializer "active_job.set_reloader_hook" do |app|
|
@@ -9,12 +9,14 @@ module ActiveJob
|
|
9
9
|
extend ActiveSupport::Autoload
|
10
10
|
|
11
11
|
autoload :ObjectSerializer
|
12
|
+
autoload :TimeObjectSerializer
|
12
13
|
autoload :SymbolSerializer
|
13
14
|
autoload :DurationSerializer
|
14
15
|
autoload :DateTimeSerializer
|
15
16
|
autoload :DateSerializer
|
16
17
|
autoload :TimeWithZoneSerializer
|
17
18
|
autoload :TimeSerializer
|
19
|
+
autoload :ModuleSerializer
|
18
20
|
|
19
21
|
mattr_accessor :_additional_serializers
|
20
22
|
self._additional_serializers = Set.new
|
@@ -58,6 +60,7 @@ module ActiveJob
|
|
58
60
|
DateTimeSerializer,
|
59
61
|
DateSerializer,
|
60
62
|
TimeWithZoneSerializer,
|
61
|
-
TimeSerializer
|
63
|
+
TimeSerializer,
|
64
|
+
ModuleSerializer
|
62
65
|
end
|
63
66
|
end
|
@@ -2,11 +2,7 @@
|
|
2
2
|
|
3
3
|
module ActiveJob
|
4
4
|
module Serializers
|
5
|
-
class DateTimeSerializer <
|
6
|
-
def serialize(time)
|
7
|
-
super("value" => time.iso8601)
|
8
|
-
end
|
9
|
-
|
5
|
+
class DateTimeSerializer < TimeObjectSerializer # :nodoc:
|
10
6
|
def deserialize(hash)
|
11
7
|
DateTime.iso8601(hash["value"])
|
12
8
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveJob
|
4
|
+
module Serializers
|
5
|
+
class ModuleSerializer < ObjectSerializer # :nodoc:
|
6
|
+
def serialize(constant)
|
7
|
+
super("value" => constant.name)
|
8
|
+
end
|
9
|
+
|
10
|
+
def deserialize(hash)
|
11
|
+
hash["value"].constantize
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def klass
|
16
|
+
Module
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -2,11 +2,7 @@
|
|
2
2
|
|
3
3
|
module ActiveJob
|
4
4
|
module Serializers
|
5
|
-
class TimeSerializer <
|
6
|
-
def serialize(time)
|
7
|
-
super("value" => time.iso8601)
|
8
|
-
end
|
9
|
-
|
5
|
+
class TimeSerializer < TimeObjectSerializer # :nodoc:
|
10
6
|
def deserialize(hash)
|
11
7
|
Time.iso8601(hash["value"])
|
12
8
|
end
|
@@ -2,11 +2,7 @@
|
|
2
2
|
|
3
3
|
module ActiveJob
|
4
4
|
module Serializers
|
5
|
-
class TimeWithZoneSerializer <
|
6
|
-
def serialize(time)
|
7
|
-
super("value" => time.iso8601)
|
8
|
-
end
|
9
|
-
|
5
|
+
class TimeWithZoneSerializer < TimeObjectSerializer # :nodoc:
|
10
6
|
def deserialize(hash)
|
11
7
|
Time.iso8601(hash["value"]).in_time_zone
|
12
8
|
end
|
@@ -9,6 +9,8 @@ module ActiveJob
|
|
9
9
|
:performed_jobs, :performed_jobs=,
|
10
10
|
to: :queue_adapter
|
11
11
|
|
12
|
+
include ActiveSupport::Testing::Assertions
|
13
|
+
|
12
14
|
module TestQueueAdapter
|
13
15
|
extend ActiveSupport::Concern
|
14
16
|
|
@@ -117,17 +119,17 @@ module ActiveJob
|
|
117
119
|
# HelloJob.perform_later('elfassy')
|
118
120
|
# end
|
119
121
|
# end
|
120
|
-
def assert_enqueued_jobs(number, only: nil, except: nil, queue: nil)
|
122
|
+
def assert_enqueued_jobs(number, only: nil, except: nil, queue: nil, &block)
|
121
123
|
if block_given?
|
122
|
-
|
124
|
+
original_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
|
123
125
|
|
124
|
-
|
126
|
+
assert_nothing_raised(&block)
|
125
127
|
|
126
|
-
|
128
|
+
new_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
|
127
129
|
|
128
|
-
actual_count =
|
130
|
+
actual_count = (new_jobs - original_jobs).count
|
129
131
|
else
|
130
|
-
actual_count = enqueued_jobs_with(only: only, except: except, queue: queue)
|
132
|
+
actual_count = enqueued_jobs_with(only: only, except: except, queue: queue).count
|
131
133
|
end
|
132
134
|
|
133
135
|
assert_equal number, actual_count, "#{number} jobs expected, but #{actual_count} were enqueued"
|
@@ -279,7 +281,7 @@ module ActiveJob
|
|
279
281
|
|
280
282
|
performed_jobs_size = new_count - original_count
|
281
283
|
else
|
282
|
-
performed_jobs_size = performed_jobs_with(only: only, except: except, queue: queue)
|
284
|
+
performed_jobs_size = performed_jobs_with(only: only, except: except, queue: queue).count
|
283
285
|
end
|
284
286
|
|
285
287
|
assert_equal number, performed_jobs_size, "#{number} jobs expected, but #{performed_jobs_size} were performed"
|
@@ -345,44 +347,40 @@ module ActiveJob
|
|
345
347
|
#
|
346
348
|
# def test_assert_enqueued_with
|
347
349
|
# MyJob.perform_later(1,2,3)
|
348
|
-
# assert_enqueued_with(job: MyJob, args: [1,2,3]
|
350
|
+
# assert_enqueued_with(job: MyJob, args: [1,2,3])
|
349
351
|
#
|
350
|
-
# MyJob.set(wait_until: Date.tomorrow.noon).perform_later
|
351
|
-
# assert_enqueued_with(
|
352
|
+
# MyJob.set(wait_until: Date.tomorrow.noon, queue: "my_queue").perform_later
|
353
|
+
# assert_enqueued_with(at: Date.tomorrow.noon, queue: "my_queue")
|
352
354
|
# end
|
353
355
|
#
|
354
|
-
# The
|
356
|
+
# The given arguments may also be specified as matcher procs that return a
|
357
|
+
# boolean value indicating whether a job's attribute meets certain criteria.
|
355
358
|
#
|
356
|
-
#
|
359
|
+
# For example, a proc can be used to match a range of times:
|
357
360
|
#
|
358
361
|
# def test_assert_enqueued_with
|
359
|
-
#
|
360
|
-
#
|
361
|
-
#
|
362
|
+
# at_matcher = ->(job_at) { (Date.yesterday..Date.tomorrow).cover?(job_at) }
|
363
|
+
#
|
364
|
+
# MyJob.set(wait_until: Date.today.noon).perform_later
|
362
365
|
#
|
363
|
-
# MyJob
|
364
|
-
# assert_enqueued_with(job: MyJob, at: expected_time)
|
366
|
+
# assert_enqueued_with(job: MyJob, at: at_matcher)
|
365
367
|
# end
|
366
368
|
#
|
367
|
-
#
|
368
|
-
# Your proc needs to return a boolean value determining if
|
369
|
-
# the job's arguments matches your expectation. This is useful to check only
|
370
|
-
# for a subset of arguments.
|
369
|
+
# A proc can also be used to match a subset of a job's args:
|
371
370
|
#
|
372
371
|
# def test_assert_enqueued_with
|
373
|
-
#
|
374
|
-
#
|
375
|
-
#
|
372
|
+
# args_matcher = ->(job_args) { job_args[0].key?(:foo) }
|
373
|
+
#
|
374
|
+
# MyJob.perform_later(foo: "bar", other_arg: "No need to check in the test")
|
376
375
|
#
|
377
|
-
#
|
378
|
-
# assert_enqueued_with(job: MyJob, args: expected_args, queue: 'low')
|
376
|
+
# assert_enqueued_with(job: MyJob, args: args_matcher)
|
379
377
|
# end
|
380
378
|
#
|
381
379
|
# If a block is passed, asserts that the block will cause the job to be
|
382
380
|
# enqueued with the given arguments.
|
383
381
|
#
|
384
382
|
# def test_assert_enqueued_with
|
385
|
-
# assert_enqueued_with(job: MyJob, args: [1,2,3]
|
383
|
+
# assert_enqueued_with(job: MyJob, args: [1,2,3]) do
|
386
384
|
# MyJob.perform_later(1,2,3)
|
387
385
|
# end
|
388
386
|
#
|
@@ -390,22 +388,24 @@ module ActiveJob
|
|
390
388
|
# MyJob.set(wait_until: Date.tomorrow.noon).perform_later
|
391
389
|
# end
|
392
390
|
# end
|
393
|
-
def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil)
|
391
|
+
def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil, &block)
|
394
392
|
expected = { job: job, args: args, at: at, queue: queue }.compact
|
395
393
|
expected_args = prepare_args_for_assertion(expected)
|
394
|
+
potential_matches = []
|
396
395
|
|
397
396
|
if block_given?
|
398
|
-
|
397
|
+
original_enqueued_jobs = enqueued_jobs.dup
|
399
398
|
|
400
|
-
|
399
|
+
assert_nothing_raised(&block)
|
401
400
|
|
402
|
-
jobs = enqueued_jobs
|
401
|
+
jobs = enqueued_jobs - original_enqueued_jobs
|
403
402
|
else
|
404
403
|
jobs = enqueued_jobs
|
405
404
|
end
|
406
405
|
|
407
406
|
matching_job = jobs.find do |enqueued_job|
|
408
407
|
deserialized_job = deserialize_args_for_assertion(enqueued_job)
|
408
|
+
potential_matches << deserialized_job
|
409
409
|
|
410
410
|
expected_args.all? do |key, value|
|
411
411
|
if value.respond_to?(:call)
|
@@ -416,7 +416,9 @@ module ActiveJob
|
|
416
416
|
end
|
417
417
|
end
|
418
418
|
|
419
|
-
|
419
|
+
message = +"No enqueued job found with #{expected}"
|
420
|
+
message << "\n\nPotential matches: #{potential_matches.join("\n")}" if potential_matches.present?
|
421
|
+
assert matching_job, message
|
420
422
|
instantiate_job(matching_job)
|
421
423
|
end
|
422
424
|
|
@@ -427,42 +429,40 @@ module ActiveJob
|
|
427
429
|
#
|
428
430
|
# perform_enqueued_jobs
|
429
431
|
#
|
430
|
-
# assert_performed_with(job: MyJob, args: [1,2,3]
|
432
|
+
# assert_performed_with(job: MyJob, args: [1,2,3])
|
431
433
|
#
|
432
|
-
# MyJob.set(wait_until: Date.tomorrow.noon).perform_later
|
434
|
+
# MyJob.set(wait_until: Date.tomorrow.noon, queue: "my_queue").perform_later
|
433
435
|
#
|
434
436
|
# perform_enqueued_jobs
|
435
437
|
#
|
436
|
-
# assert_performed_with(
|
438
|
+
# assert_performed_with(at: Date.tomorrow.noon, queue: "my_queue")
|
437
439
|
# end
|
438
440
|
#
|
439
|
-
# The
|
441
|
+
# The given arguments may also be specified as matcher procs that return a
|
442
|
+
# boolean value indicating whether a job's attribute meets certain criteria.
|
440
443
|
#
|
441
|
-
#
|
444
|
+
# For example, a proc can be used to match a range of times:
|
442
445
|
#
|
443
|
-
# def
|
444
|
-
#
|
445
|
-
#
|
446
|
-
#
|
446
|
+
# def test_assert_performed_with
|
447
|
+
# at_matcher = ->(job_at) { (Date.yesterday..Date.tomorrow).cover?(job_at) }
|
448
|
+
#
|
449
|
+
# MyJob.set(wait_until: Date.today.noon).perform_later
|
450
|
+
#
|
451
|
+
# perform_enqueued_jobs
|
447
452
|
#
|
448
|
-
# MyJob
|
449
|
-
# assert_enqueued_with(job: MyJob, at: expected_time)
|
453
|
+
# assert_performed_with(job: MyJob, at: at_matcher)
|
450
454
|
# end
|
451
455
|
#
|
452
|
-
#
|
453
|
-
# Your proc needs to return a boolean value determining if
|
454
|
-
# the job's arguments matches your expectation. This is useful to check only
|
455
|
-
# for a subset of arguments.
|
456
|
+
# A proc can also be used to match a subset of a job's args:
|
456
457
|
#
|
457
458
|
# def test_assert_performed_with
|
458
|
-
#
|
459
|
-
#
|
460
|
-
#
|
461
|
-
# MyJob.perform_later(foo: 'bar', other_arg: 'No need to check in the test')
|
459
|
+
# args_matcher = ->(job_args) { job_args[0].key?(:foo) }
|
460
|
+
#
|
461
|
+
# MyJob.perform_later(foo: "bar", other_arg: "No need to check in the test")
|
462
462
|
#
|
463
463
|
# perform_enqueued_jobs
|
464
464
|
#
|
465
|
-
# assert_performed_with(job: MyJob, args:
|
465
|
+
# assert_performed_with(job: MyJob, args: args_matcher)
|
466
466
|
# end
|
467
467
|
#
|
468
468
|
# If a block is passed, that block performs all of the jobs that were
|
@@ -470,7 +470,7 @@ module ActiveJob
|
|
470
470
|
# the job has been performed with the given arguments in the block.
|
471
471
|
#
|
472
472
|
# def test_assert_performed_with
|
473
|
-
# assert_performed_with(job: MyJob, args: [1,2,3]
|
473
|
+
# assert_performed_with(job: MyJob, args: [1,2,3]) do
|
474
474
|
# MyJob.perform_later(1,2,3)
|
475
475
|
# end
|
476
476
|
#
|
@@ -481,6 +481,7 @@ module ActiveJob
|
|
481
481
|
def assert_performed_with(job: nil, args: nil, at: nil, queue: nil, &block)
|
482
482
|
expected = { job: job, args: args, at: at, queue: queue }.compact
|
483
483
|
expected_args = prepare_args_for_assertion(expected)
|
484
|
+
potential_matches = []
|
484
485
|
|
485
486
|
if block_given?
|
486
487
|
original_performed_jobs_count = performed_jobs.count
|
@@ -494,6 +495,7 @@ module ActiveJob
|
|
494
495
|
|
495
496
|
matching_job = jobs.find do |enqueued_job|
|
496
497
|
deserialized_job = deserialize_args_for_assertion(enqueued_job)
|
498
|
+
potential_matches << deserialized_job
|
497
499
|
|
498
500
|
expected_args.all? do |key, value|
|
499
501
|
if value.respond_to?(:call)
|
@@ -504,7 +506,10 @@ module ActiveJob
|
|
504
506
|
end
|
505
507
|
end
|
506
508
|
|
507
|
-
|
509
|
+
message = +"No performed job found with #{expected}"
|
510
|
+
message << "\n\nPotential matches: #{potential_matches.join("\n")}" if potential_matches.present?
|
511
|
+
assert matching_job, message
|
512
|
+
|
508
513
|
instantiate_job(matching_job)
|
509
514
|
end
|
510
515
|
|
@@ -563,8 +568,10 @@ module ActiveJob
|
|
563
568
|
# assert_performed_jobs 1
|
564
569
|
# end
|
565
570
|
#
|
566
|
-
|
567
|
-
|
571
|
+
# If the +:at+ option is specified, then only run jobs enqueued to run
|
572
|
+
# immediately or before the given time
|
573
|
+
def perform_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil, &block)
|
574
|
+
return flush_enqueued_jobs(only: only, except: except, queue: queue, at: at) unless block_given?
|
568
575
|
|
569
576
|
validate_option(only: only, except: except)
|
570
577
|
|
@@ -573,6 +580,7 @@ module ActiveJob
|
|
573
580
|
old_filter = queue_adapter.filter
|
574
581
|
old_reject = queue_adapter.reject
|
575
582
|
old_queue = queue_adapter.queue
|
583
|
+
old_at = queue_adapter.at
|
576
584
|
|
577
585
|
begin
|
578
586
|
queue_adapter.perform_enqueued_jobs = true
|
@@ -580,14 +588,16 @@ module ActiveJob
|
|
580
588
|
queue_adapter.filter = only
|
581
589
|
queue_adapter.reject = except
|
582
590
|
queue_adapter.queue = queue
|
591
|
+
queue_adapter.at = at
|
583
592
|
|
584
|
-
|
593
|
+
assert_nothing_raised(&block)
|
585
594
|
ensure
|
586
595
|
queue_adapter.perform_enqueued_jobs = old_perform_enqueued_jobs
|
587
596
|
queue_adapter.perform_enqueued_at_jobs = old_perform_enqueued_at_jobs
|
588
597
|
queue_adapter.filter = old_filter
|
589
598
|
queue_adapter.reject = old_reject
|
590
599
|
queue_adapter.queue = old_queue
|
600
|
+
queue_adapter.at = old_at
|
591
601
|
end
|
592
602
|
end
|
593
603
|
|
@@ -609,10 +619,10 @@ module ActiveJob
|
|
609
619
|
performed_jobs.clear
|
610
620
|
end
|
611
621
|
|
612
|
-
def jobs_with(jobs, only: nil, except: nil, queue: nil)
|
622
|
+
def jobs_with(jobs, only: nil, except: nil, queue: nil, at: nil)
|
613
623
|
validate_option(only: only, except: except)
|
614
624
|
|
615
|
-
jobs.
|
625
|
+
jobs.dup.select do |job|
|
616
626
|
job_class = job.fetch(:job)
|
617
627
|
|
618
628
|
if only
|
@@ -625,6 +635,10 @@ module ActiveJob
|
|
625
635
|
next false unless queue.to_s == job.fetch(:queue, job_class.queue_name)
|
626
636
|
end
|
627
637
|
|
638
|
+
if at && job[:at]
|
639
|
+
next false if job[:at] > at.to_f
|
640
|
+
end
|
641
|
+
|
628
642
|
yield job if block_given?
|
629
643
|
|
630
644
|
true
|
@@ -637,41 +651,28 @@ module ActiveJob
|
|
637
651
|
->(job) { Array(filter).include?(job.fetch(:job)) }
|
638
652
|
end
|
639
653
|
|
640
|
-
def enqueued_jobs_with(only: nil, except: nil, queue: nil, &block)
|
641
|
-
jobs_with(enqueued_jobs, only: only, except: except, queue: queue, &block)
|
654
|
+
def enqueued_jobs_with(only: nil, except: nil, queue: nil, at: nil, &block)
|
655
|
+
jobs_with(enqueued_jobs, only: only, except: except, queue: queue, at: at, &block)
|
642
656
|
end
|
643
657
|
|
644
658
|
def performed_jobs_with(only: nil, except: nil, queue: nil, &block)
|
645
659
|
jobs_with(performed_jobs, only: only, except: except, queue: queue, &block)
|
646
660
|
end
|
647
661
|
|
648
|
-
def flush_enqueued_jobs(only: nil, except: nil, queue: nil)
|
649
|
-
enqueued_jobs_with(only: only, except: except, queue: queue) do |payload|
|
650
|
-
|
662
|
+
def flush_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil)
|
663
|
+
enqueued_jobs_with(only: only, except: except, queue: queue, at: at) do |payload|
|
664
|
+
queue_adapter.enqueued_jobs.delete(payload)
|
651
665
|
queue_adapter.performed_jobs << payload
|
652
|
-
|
666
|
+
instantiate_job(payload).perform_now
|
667
|
+
end.count
|
653
668
|
end
|
654
669
|
|
655
670
|
def prepare_args_for_assertion(args)
|
656
671
|
args.dup.tap do |arguments|
|
657
|
-
if arguments[:at]
|
672
|
+
if arguments[:at].acts_like?(:time)
|
658
673
|
at_range = arguments[:at] - 1..arguments[:at] + 1
|
659
674
|
arguments[:at] = ->(at) { at_range.cover?(at) }
|
660
675
|
end
|
661
|
-
arguments[:args] = round_time_arguments(arguments[:args]) if arguments[:args]
|
662
|
-
end
|
663
|
-
end
|
664
|
-
|
665
|
-
def round_time_arguments(argument)
|
666
|
-
case argument
|
667
|
-
when Time, ActiveSupport::TimeWithZone, DateTime
|
668
|
-
argument.change(usec: 0)
|
669
|
-
when Hash
|
670
|
-
argument.transform_values { |value| round_time_arguments(value) }
|
671
|
-
when Array
|
672
|
-
argument.map { |element| round_time_arguments(element) }
|
673
|
-
else
|
674
|
-
argument
|
675
676
|
end
|
676
677
|
end
|
677
678
|
|