activejob 5.2.8.1 → 6.1.6.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 +118 -57
- data/MIT-LICENSE +1 -2
- data/README.md +18 -13
- data/lib/active_job/arguments.rb +80 -30
- data/lib/active_job/base.rb +6 -1
- data/lib/active_job/callbacks.rb +46 -3
- data/lib/active_job/configured_job.rb +2 -0
- data/lib/active_job/core.rb +40 -21
- data/lib/active_job/enqueuing.rb +20 -7
- data/lib/active_job/exceptions.rb +60 -28
- data/lib/active_job/execution.rb +11 -2
- 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 -101
- data/lib/active_job/queue_adapter.rb +5 -0
- data/lib/active_job/queue_adapters/async_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/backburner_adapter.rb +2 -2
- data/lib/active_job/queue_adapters/inline_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/que_adapter.rb +2 -2
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +2 -2
- data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/test_adapter.rb +32 -14
- data/lib/active_job/queue_adapters.rb +13 -11
- data/lib/active_job/queue_name.rb +23 -3
- data/lib/active_job/railtie.rb +20 -1
- data/lib/active_job/serializers/date_serializer.rb +20 -0
- data/lib/active_job/serializers/date_time_serializer.rb +16 -0
- data/lib/active_job/serializers/duration_serializer.rb +23 -0
- data/lib/active_job/serializers/module_serializer.rb +20 -0
- data/lib/active_job/serializers/object_serializer.rb +53 -0
- data/lib/active_job/serializers/symbol_serializer.rb +20 -0
- data/lib/active_job/serializers/time_object_serializer.rb +13 -0
- data/lib/active_job/serializers/time_serializer.rb +16 -0
- data/lib/active_job/serializers/time_with_zone_serializer.rb +16 -0
- data/lib/active_job/serializers.rb +66 -0
- data/lib/active_job/test_helper.rb +317 -68
- data/lib/active_job/timezones.rb +13 -0
- data/lib/active_job/translation.rb +1 -1
- data/lib/active_job.rb +2 -1
- data/lib/rails/generators/job/job_generator.rb +4 -0
- metadata +25 -9
- data/lib/active_job/queue_adapters/qu_adapter.rb +0 -46
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/core_ext/class/subclasses"
|
4
|
-
require "active_support/
|
4
|
+
require "active_support/testing/assertions"
|
5
5
|
|
6
6
|
module ActiveJob
|
7
7
|
# Provides helper methods for testing Active Job
|
@@ -10,6 +10,8 @@ module ActiveJob
|
|
10
10
|
:performed_jobs, :performed_jobs=,
|
11
11
|
to: :queue_adapter
|
12
12
|
|
13
|
+
include ActiveSupport::Testing::Assertions
|
14
|
+
|
13
15
|
module TestQueueAdapter
|
14
16
|
extend ActiveSupport::Concern
|
15
17
|
|
@@ -52,7 +54,7 @@ module ActiveJob
|
|
52
54
|
queue_adapter_changed_jobs.each { |klass| klass.disable_test_adapter }
|
53
55
|
end
|
54
56
|
|
55
|
-
# Specifies the queue adapter to use with all
|
57
|
+
# Specifies the queue adapter to use with all Active Job test helpers.
|
56
58
|
#
|
57
59
|
# Returns an instance of the queue adapter and defaults to
|
58
60
|
# <tt>ActiveJob::QueueAdapters::TestAdapter</tt>.
|
@@ -75,7 +77,7 @@ module ActiveJob
|
|
75
77
|
# assert_enqueued_jobs 2
|
76
78
|
# end
|
77
79
|
#
|
78
|
-
# If a block is passed, that block will cause the specified number of
|
80
|
+
# If a block is passed, asserts that the block will cause the specified number of
|
79
81
|
# jobs to be enqueued.
|
80
82
|
#
|
81
83
|
# def test_jobs_again
|
@@ -89,7 +91,7 @@ module ActiveJob
|
|
89
91
|
# end
|
90
92
|
# end
|
91
93
|
#
|
92
|
-
#
|
94
|
+
# Asserts the number of times a specific job was enqueued by passing +:only+ option.
|
93
95
|
#
|
94
96
|
# def test_logging_job
|
95
97
|
# assert_enqueued_jobs 1, only: LoggingJob do
|
@@ -98,7 +100,7 @@ module ActiveJob
|
|
98
100
|
# end
|
99
101
|
# end
|
100
102
|
#
|
101
|
-
#
|
103
|
+
# Asserts the number of times a job except specific class was enqueued by passing +:except+ option.
|
102
104
|
#
|
103
105
|
# def test_logging_job
|
104
106
|
# assert_enqueued_jobs 1, except: HelloJob do
|
@@ -107,7 +109,10 @@ module ActiveJob
|
|
107
109
|
# end
|
108
110
|
# end
|
109
111
|
#
|
110
|
-
#
|
112
|
+
# +:only+ and +:except+ options accepts Class, Array of Class or Proc. When passed a Proc,
|
113
|
+
# a hash containing the job's class and it's argument are passed as argument.
|
114
|
+
#
|
115
|
+
# Asserts the number of times a job is enqueued to a specific queue by passing +:queue+ option.
|
111
116
|
#
|
112
117
|
# def test_logging_job
|
113
118
|
# assert_enqueued_jobs 2, queue: 'default' do
|
@@ -115,16 +120,20 @@ module ActiveJob
|
|
115
120
|
# HelloJob.perform_later('elfassy')
|
116
121
|
# end
|
117
122
|
# end
|
118
|
-
def assert_enqueued_jobs(number, only: nil, except: nil, queue: nil)
|
123
|
+
def assert_enqueued_jobs(number, only: nil, except: nil, queue: nil, &block)
|
119
124
|
if block_given?
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
125
|
+
original_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
|
126
|
+
|
127
|
+
assert_nothing_raised(&block)
|
128
|
+
|
129
|
+
new_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
|
130
|
+
|
131
|
+
actual_count = (new_jobs - original_jobs).count
|
124
132
|
else
|
125
|
-
actual_count =
|
126
|
-
assert_equal number, actual_count, "#{number} jobs expected, but #{actual_count} were enqueued"
|
133
|
+
actual_count = enqueued_jobs_with(only: only, except: except, queue: queue).count
|
127
134
|
end
|
135
|
+
|
136
|
+
assert_equal number, actual_count, "#{number} jobs expected, but #{actual_count} were enqueued"
|
128
137
|
end
|
129
138
|
|
130
139
|
# Asserts that no jobs have been enqueued.
|
@@ -135,7 +144,7 @@ module ActiveJob
|
|
135
144
|
# assert_enqueued_jobs 1
|
136
145
|
# end
|
137
146
|
#
|
138
|
-
# If a block is passed, that block
|
147
|
+
# If a block is passed, asserts that the block will not cause any job to be enqueued.
|
139
148
|
#
|
140
149
|
# def test_jobs_again
|
141
150
|
# assert_no_enqueued_jobs do
|
@@ -143,7 +152,7 @@ module ActiveJob
|
|
143
152
|
# end
|
144
153
|
# end
|
145
154
|
#
|
146
|
-
#
|
155
|
+
# Asserts that no jobs of a specific kind are enqueued by passing +:only+ option.
|
147
156
|
#
|
148
157
|
# def test_no_logging
|
149
158
|
# assert_no_enqueued_jobs only: LoggingJob do
|
@@ -151,7 +160,7 @@ module ActiveJob
|
|
151
160
|
# end
|
152
161
|
# end
|
153
162
|
#
|
154
|
-
#
|
163
|
+
# Asserts that no jobs except specific class are enqueued by passing +:except+ option.
|
155
164
|
#
|
156
165
|
# def test_no_logging
|
157
166
|
# assert_no_enqueued_jobs except: HelloJob do
|
@@ -159,16 +168,27 @@ module ActiveJob
|
|
159
168
|
# end
|
160
169
|
# end
|
161
170
|
#
|
171
|
+
# +:only+ and +:except+ options accepts Class, Array of Class or Proc. When passed a Proc,
|
172
|
+
# a hash containing the job's class and it's argument are passed as argument.
|
173
|
+
#
|
174
|
+
# Asserts that no jobs are enqueued to a specific queue by passing +:queue+ option
|
175
|
+
#
|
176
|
+
# def test_no_logging
|
177
|
+
# assert_no_enqueued_jobs queue: 'default' do
|
178
|
+
# LoggingJob.set(queue: :some_queue).perform_later
|
179
|
+
# end
|
180
|
+
# end
|
181
|
+
#
|
162
182
|
# Note: This assertion is simply a shortcut for:
|
163
183
|
#
|
164
184
|
# assert_enqueued_jobs 0, &block
|
165
|
-
def assert_no_enqueued_jobs(only: nil, except: nil, &block)
|
166
|
-
assert_enqueued_jobs 0, only: only, except: except, &block
|
185
|
+
def assert_no_enqueued_jobs(only: nil, except: nil, queue: nil, &block)
|
186
|
+
assert_enqueued_jobs 0, only: only, except: except, queue: queue, &block
|
167
187
|
end
|
168
188
|
|
169
189
|
# Asserts that the number of performed jobs matches the given number.
|
170
190
|
# If no block is passed, <tt>perform_enqueued_jobs</tt>
|
171
|
-
# must be called around the job call.
|
191
|
+
# must be called around or after the job call.
|
172
192
|
#
|
173
193
|
# def test_jobs
|
174
194
|
# assert_performed_jobs 0
|
@@ -178,13 +198,14 @@ module ActiveJob
|
|
178
198
|
# end
|
179
199
|
# assert_performed_jobs 1
|
180
200
|
#
|
181
|
-
#
|
182
|
-
#
|
183
|
-
#
|
184
|
-
#
|
201
|
+
# HelloJob.perform_later('yves')
|
202
|
+
#
|
203
|
+
# perform_enqueued_jobs
|
204
|
+
#
|
205
|
+
# assert_performed_jobs 2
|
185
206
|
# end
|
186
207
|
#
|
187
|
-
# If a block is passed, that block
|
208
|
+
# If a block is passed, asserts that the block will cause the specified number of
|
188
209
|
# jobs to be performed.
|
189
210
|
#
|
190
211
|
# def test_jobs_again
|
@@ -198,7 +219,7 @@ module ActiveJob
|
|
198
219
|
# end
|
199
220
|
# end
|
200
221
|
#
|
201
|
-
#
|
222
|
+
# This method also supports filtering. If the +:only+ option is specified,
|
202
223
|
# then only the listed job(s) will be performed.
|
203
224
|
#
|
204
225
|
# def test_hello_job
|
@@ -208,7 +229,7 @@ module ActiveJob
|
|
208
229
|
# end
|
209
230
|
# end
|
210
231
|
#
|
211
|
-
# Also if the
|
232
|
+
# Also if the +:except+ option is specified,
|
212
233
|
# then the job(s) except specific class will be performed.
|
213
234
|
#
|
214
235
|
# def test_hello_job
|
@@ -229,17 +250,42 @@ module ActiveJob
|
|
229
250
|
# end
|
230
251
|
# end
|
231
252
|
# end
|
232
|
-
|
253
|
+
#
|
254
|
+
# A proc may also be specified. When passed a Proc, the job's instance will be passed as argument.
|
255
|
+
#
|
256
|
+
# def test_hello_and_logging_jobs
|
257
|
+
# assert_nothing_raised do
|
258
|
+
# assert_performed_jobs(1, only: ->(job) { job.is_a?(HelloJob) }) do
|
259
|
+
# HelloJob.perform_later('jeremy')
|
260
|
+
# LoggingJob.perform_later('stewie')
|
261
|
+
# RescueJob.perform_later('david')
|
262
|
+
# end
|
263
|
+
# end
|
264
|
+
# end
|
265
|
+
#
|
266
|
+
# If the +:queue+ option is specified,
|
267
|
+
# then only the job(s) enqueued to a specific queue will be performed.
|
268
|
+
#
|
269
|
+
# def test_assert_performed_jobs_with_queue_option
|
270
|
+
# assert_performed_jobs 1, queue: :some_queue do
|
271
|
+
# HelloJob.set(queue: :some_queue).perform_later("jeremy")
|
272
|
+
# HelloJob.set(queue: :other_queue).perform_later("bogdan")
|
273
|
+
# end
|
274
|
+
# end
|
275
|
+
def assert_performed_jobs(number, only: nil, except: nil, queue: nil, &block)
|
233
276
|
if block_given?
|
234
277
|
original_count = performed_jobs.size
|
235
|
-
|
278
|
+
|
279
|
+
perform_enqueued_jobs(only: only, except: except, queue: queue, &block)
|
280
|
+
|
236
281
|
new_count = performed_jobs.size
|
237
|
-
|
238
|
-
|
282
|
+
|
283
|
+
performed_jobs_size = new_count - original_count
|
239
284
|
else
|
240
|
-
performed_jobs_size =
|
241
|
-
assert_equal number, performed_jobs_size, "#{number} jobs expected, but #{performed_jobs_size} were performed"
|
285
|
+
performed_jobs_size = performed_jobs_with(only: only, except: except, queue: queue).count
|
242
286
|
end
|
287
|
+
|
288
|
+
assert_equal number, performed_jobs_size, "#{number} jobs expected, but #{performed_jobs_size} were performed"
|
243
289
|
end
|
244
290
|
|
245
291
|
# Asserts that no jobs have been performed.
|
@@ -253,7 +299,7 @@ module ActiveJob
|
|
253
299
|
# end
|
254
300
|
# end
|
255
301
|
#
|
256
|
-
# If a block is passed, that block
|
302
|
+
# If a block is passed, asserts that the block will not cause any job to be performed.
|
257
303
|
#
|
258
304
|
# def test_jobs_again
|
259
305
|
# assert_no_performed_jobs do
|
@@ -261,7 +307,7 @@ module ActiveJob
|
|
261
307
|
# end
|
262
308
|
# end
|
263
309
|
#
|
264
|
-
# The block form supports filtering. If the
|
310
|
+
# The block form supports filtering. If the +:only+ option is specified,
|
265
311
|
# then only the listed job(s) will not be performed.
|
266
312
|
#
|
267
313
|
# def test_no_logging
|
@@ -270,7 +316,7 @@ module ActiveJob
|
|
270
316
|
# end
|
271
317
|
# end
|
272
318
|
#
|
273
|
-
# Also if the
|
319
|
+
# Also if the +:except+ option is specified,
|
274
320
|
# then the job(s) except specific class will not be performed.
|
275
321
|
#
|
276
322
|
# def test_no_logging
|
@@ -279,17 +325,63 @@ module ActiveJob
|
|
279
325
|
# end
|
280
326
|
# end
|
281
327
|
#
|
328
|
+
# +:only+ and +:except+ options accepts Class, Array of Class or Proc. When passed a Proc,
|
329
|
+
# an instance of the job will be passed as argument.
|
330
|
+
#
|
331
|
+
# If the +:queue+ option is specified,
|
332
|
+
# then only the job(s) enqueued to a specific queue will not be performed.
|
333
|
+
#
|
334
|
+
# def test_assert_no_performed_jobs_with_queue_option
|
335
|
+
# assert_no_performed_jobs queue: :some_queue do
|
336
|
+
# HelloJob.set(queue: :other_queue).perform_later("jeremy")
|
337
|
+
# end
|
338
|
+
# end
|
339
|
+
#
|
282
340
|
# Note: This assertion is simply a shortcut for:
|
283
341
|
#
|
284
342
|
# assert_performed_jobs 0, &block
|
285
|
-
def assert_no_performed_jobs(only: nil, except: nil, &block)
|
286
|
-
assert_performed_jobs 0, only: only, except: except, &block
|
343
|
+
def assert_no_performed_jobs(only: nil, except: nil, queue: nil, &block)
|
344
|
+
assert_performed_jobs 0, only: only, except: except, queue: queue, &block
|
287
345
|
end
|
288
346
|
|
289
|
-
# Asserts that the job
|
347
|
+
# Asserts that the job has been enqueued with the given arguments.
|
348
|
+
#
|
349
|
+
# def test_assert_enqueued_with
|
350
|
+
# MyJob.perform_later(1,2,3)
|
351
|
+
# assert_enqueued_with(job: MyJob, args: [1,2,3])
|
352
|
+
#
|
353
|
+
# MyJob.set(wait_until: Date.tomorrow.noon, queue: "my_queue").perform_later
|
354
|
+
# assert_enqueued_with(at: Date.tomorrow.noon, queue: "my_queue")
|
355
|
+
# end
|
356
|
+
#
|
357
|
+
# The given arguments may also be specified as matcher procs that return a
|
358
|
+
# boolean value indicating whether a job's attribute meets certain criteria.
|
359
|
+
#
|
360
|
+
# For example, a proc can be used to match a range of times:
|
361
|
+
#
|
362
|
+
# def test_assert_enqueued_with
|
363
|
+
# at_matcher = ->(job_at) { (Date.yesterday..Date.tomorrow).cover?(job_at) }
|
364
|
+
#
|
365
|
+
# MyJob.set(wait_until: Date.today.noon).perform_later
|
366
|
+
#
|
367
|
+
# assert_enqueued_with(job: MyJob, at: at_matcher)
|
368
|
+
# end
|
369
|
+
#
|
370
|
+
# A proc can also be used to match a subset of a job's args:
|
290
371
|
#
|
291
372
|
# def test_assert_enqueued_with
|
292
|
-
#
|
373
|
+
# args_matcher = ->(job_args) { job_args[0].key?(:foo) }
|
374
|
+
#
|
375
|
+
# MyJob.perform_later(foo: "bar", other_arg: "No need to check in the test")
|
376
|
+
#
|
377
|
+
# assert_enqueued_with(job: MyJob, args: args_matcher)
|
378
|
+
# end
|
379
|
+
#
|
380
|
+
# If a block is passed, asserts that the block will cause the job to be
|
381
|
+
# enqueued with the given arguments.
|
382
|
+
#
|
383
|
+
# def test_assert_enqueued_with
|
384
|
+
# assert_enqueued_with(job: MyJob, args: [1,2,3]) do
|
293
385
|
# MyJob.perform_later(1,2,3)
|
294
386
|
# end
|
295
387
|
#
|
@@ -297,24 +389,89 @@ module ActiveJob
|
|
297
389
|
# MyJob.set(wait_until: Date.tomorrow.noon).perform_later
|
298
390
|
# end
|
299
391
|
# end
|
300
|
-
def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil)
|
301
|
-
original_enqueued_jobs_count = enqueued_jobs.count
|
392
|
+
def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil, &block)
|
302
393
|
expected = { job: job, args: args, at: at, queue: queue }.compact
|
303
394
|
expected_args = prepare_args_for_assertion(expected)
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
395
|
+
potential_matches = []
|
396
|
+
|
397
|
+
if block_given?
|
398
|
+
original_enqueued_jobs = enqueued_jobs.dup
|
399
|
+
|
400
|
+
assert_nothing_raised(&block)
|
401
|
+
|
402
|
+
jobs = enqueued_jobs - original_enqueued_jobs
|
403
|
+
else
|
404
|
+
jobs = enqueued_jobs
|
405
|
+
end
|
406
|
+
|
407
|
+
matching_job = jobs.find do |enqueued_job|
|
408
|
+
deserialized_job = deserialize_args_for_assertion(enqueued_job)
|
409
|
+
potential_matches << deserialized_job
|
410
|
+
|
411
|
+
expected_args.all? do |key, value|
|
412
|
+
if value.respond_to?(:call)
|
413
|
+
value.call(deserialized_job[key])
|
414
|
+
else
|
415
|
+
value == deserialized_job[key]
|
416
|
+
end
|
417
|
+
end
|
309
418
|
end
|
310
|
-
|
419
|
+
|
420
|
+
message = +"No enqueued job found with #{expected}"
|
421
|
+
message << "\n\nPotential matches: #{potential_matches.join("\n")}" if potential_matches.present?
|
422
|
+
assert matching_job, message
|
311
423
|
instantiate_job(matching_job)
|
312
424
|
end
|
313
425
|
|
314
|
-
# Asserts that the job
|
426
|
+
# Asserts that the job has been performed with the given arguments.
|
427
|
+
#
|
428
|
+
# def test_assert_performed_with
|
429
|
+
# MyJob.perform_later(1,2,3)
|
430
|
+
#
|
431
|
+
# perform_enqueued_jobs
|
432
|
+
#
|
433
|
+
# assert_performed_with(job: MyJob, args: [1,2,3])
|
434
|
+
#
|
435
|
+
# MyJob.set(wait_until: Date.tomorrow.noon, queue: "my_queue").perform_later
|
436
|
+
#
|
437
|
+
# perform_enqueued_jobs
|
438
|
+
#
|
439
|
+
# assert_performed_with(at: Date.tomorrow.noon, queue: "my_queue")
|
440
|
+
# end
|
441
|
+
#
|
442
|
+
# The given arguments may also be specified as matcher procs that return a
|
443
|
+
# boolean value indicating whether a job's attribute meets certain criteria.
|
444
|
+
#
|
445
|
+
# For example, a proc can be used to match a range of times:
|
315
446
|
#
|
316
447
|
# def test_assert_performed_with
|
317
|
-
#
|
448
|
+
# at_matcher = ->(job_at) { (Date.yesterday..Date.tomorrow).cover?(job_at) }
|
449
|
+
#
|
450
|
+
# MyJob.set(wait_until: Date.today.noon).perform_later
|
451
|
+
#
|
452
|
+
# perform_enqueued_jobs
|
453
|
+
#
|
454
|
+
# assert_performed_with(job: MyJob, at: at_matcher)
|
455
|
+
# end
|
456
|
+
#
|
457
|
+
# A proc can also be used to match a subset of a job's args:
|
458
|
+
#
|
459
|
+
# def test_assert_performed_with
|
460
|
+
# args_matcher = ->(job_args) { job_args[0].key?(:foo) }
|
461
|
+
#
|
462
|
+
# MyJob.perform_later(foo: "bar", other_arg: "No need to check in the test")
|
463
|
+
#
|
464
|
+
# perform_enqueued_jobs
|
465
|
+
#
|
466
|
+
# assert_performed_with(job: MyJob, args: args_matcher)
|
467
|
+
# end
|
468
|
+
#
|
469
|
+
# If a block is passed, that block performs all of the jobs that were
|
470
|
+
# enqueued throughout the duration of the block and asserts that
|
471
|
+
# the job has been performed with the given arguments in the block.
|
472
|
+
#
|
473
|
+
# def test_assert_performed_with
|
474
|
+
# assert_performed_with(job: MyJob, args: [1,2,3]) do
|
318
475
|
# MyJob.perform_later(1,2,3)
|
319
476
|
# end
|
320
477
|
#
|
@@ -322,21 +479,44 @@ module ActiveJob
|
|
322
479
|
# MyJob.set(wait_until: Date.tomorrow.noon).perform_later
|
323
480
|
# end
|
324
481
|
# end
|
325
|
-
def assert_performed_with(job: nil, args: nil, at: nil, queue: nil)
|
326
|
-
original_performed_jobs_count = performed_jobs.count
|
482
|
+
def assert_performed_with(job: nil, args: nil, at: nil, queue: nil, &block)
|
327
483
|
expected = { job: job, args: args, at: at, queue: queue }.compact
|
328
484
|
expected_args = prepare_args_for_assertion(expected)
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
485
|
+
potential_matches = []
|
486
|
+
|
487
|
+
if block_given?
|
488
|
+
original_performed_jobs_count = performed_jobs.count
|
489
|
+
|
490
|
+
perform_enqueued_jobs(&block)
|
491
|
+
|
492
|
+
jobs = performed_jobs.drop(original_performed_jobs_count)
|
493
|
+
else
|
494
|
+
jobs = performed_jobs
|
334
495
|
end
|
335
|
-
|
496
|
+
|
497
|
+
matching_job = jobs.find do |enqueued_job|
|
498
|
+
deserialized_job = deserialize_args_for_assertion(enqueued_job)
|
499
|
+
potential_matches << deserialized_job
|
500
|
+
|
501
|
+
expected_args.all? do |key, value|
|
502
|
+
if value.respond_to?(:call)
|
503
|
+
value.call(deserialized_job[key])
|
504
|
+
else
|
505
|
+
value == deserialized_job[key]
|
506
|
+
end
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
message = +"No performed job found with #{expected}"
|
511
|
+
message << "\n\nPotential matches: #{potential_matches.join("\n")}" if potential_matches.present?
|
512
|
+
assert matching_job, message
|
513
|
+
|
336
514
|
instantiate_job(matching_job)
|
337
515
|
end
|
338
516
|
|
339
|
-
# Performs all enqueued jobs
|
517
|
+
# Performs all enqueued jobs. If a block is given, performs all of the jobs
|
518
|
+
# that were enqueued throughout the duration of the block. If a block is
|
519
|
+
# not given, performs all of the enqueued jobs up to this point in the test.
|
340
520
|
#
|
341
521
|
# def test_perform_enqueued_jobs
|
342
522
|
# perform_enqueued_jobs do
|
@@ -345,6 +525,14 @@ module ActiveJob
|
|
345
525
|
# assert_performed_jobs 1
|
346
526
|
# end
|
347
527
|
#
|
528
|
+
# def test_perform_enqueued_jobs_without_block
|
529
|
+
# MyJob.perform_later(1, 2, 3)
|
530
|
+
#
|
531
|
+
# perform_enqueued_jobs
|
532
|
+
#
|
533
|
+
# assert_performed_jobs 1
|
534
|
+
# end
|
535
|
+
#
|
348
536
|
# This method also supports filtering. If the +:only+ option is specified,
|
349
537
|
# then only the listed job(s) will be performed.
|
350
538
|
#
|
@@ -367,24 +555,50 @@ module ActiveJob
|
|
367
555
|
# assert_performed_jobs 1
|
368
556
|
# end
|
369
557
|
#
|
370
|
-
|
558
|
+
# +:only+ and +:except+ options accepts Class, Array of Class or Proc. When passed a Proc,
|
559
|
+
# an instance of the job will be passed as argument.
|
560
|
+
#
|
561
|
+
# If the +:queue+ option is specified,
|
562
|
+
# then only the job(s) enqueued to a specific queue will be performed.
|
563
|
+
#
|
564
|
+
# def test_perform_enqueued_jobs_with_queue
|
565
|
+
# perform_enqueued_jobs queue: :some_queue do
|
566
|
+
# MyJob.set(queue: :some_queue).perform_later(1, 2, 3) # will be performed
|
567
|
+
# HelloJob.set(queue: :other_queue).perform_later(1, 2, 3) # will not be performed
|
568
|
+
# end
|
569
|
+
# assert_performed_jobs 1
|
570
|
+
# end
|
571
|
+
#
|
572
|
+
# If the +:at+ option is specified, then only run jobs enqueued to run
|
573
|
+
# immediately or before the given time
|
574
|
+
def perform_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil, &block)
|
575
|
+
return flush_enqueued_jobs(only: only, except: except, queue: queue, at: at) unless block_given?
|
576
|
+
|
371
577
|
validate_option(only: only, except: except)
|
578
|
+
|
372
579
|
old_perform_enqueued_jobs = queue_adapter.perform_enqueued_jobs
|
373
580
|
old_perform_enqueued_at_jobs = queue_adapter.perform_enqueued_at_jobs
|
374
581
|
old_filter = queue_adapter.filter
|
375
582
|
old_reject = queue_adapter.reject
|
583
|
+
old_queue = queue_adapter.queue
|
584
|
+
old_at = queue_adapter.at
|
376
585
|
|
377
586
|
begin
|
378
587
|
queue_adapter.perform_enqueued_jobs = true
|
379
588
|
queue_adapter.perform_enqueued_at_jobs = true
|
380
589
|
queue_adapter.filter = only
|
381
590
|
queue_adapter.reject = except
|
382
|
-
|
591
|
+
queue_adapter.queue = queue
|
592
|
+
queue_adapter.at = at
|
593
|
+
|
594
|
+
assert_nothing_raised(&block)
|
383
595
|
ensure
|
384
596
|
queue_adapter.perform_enqueued_jobs = old_perform_enqueued_jobs
|
385
597
|
queue_adapter.perform_enqueued_at_jobs = old_perform_enqueued_at_jobs
|
386
598
|
queue_adapter.filter = old_filter
|
387
599
|
queue_adapter.reject = old_reject
|
600
|
+
queue_adapter.queue = old_queue
|
601
|
+
queue_adapter.at = old_at
|
388
602
|
end
|
389
603
|
end
|
390
604
|
|
@@ -406,39 +620,74 @@ module ActiveJob
|
|
406
620
|
performed_jobs.clear
|
407
621
|
end
|
408
622
|
|
409
|
-
def
|
623
|
+
def jobs_with(jobs, only: nil, except: nil, queue: nil, at: nil)
|
410
624
|
validate_option(only: only, except: except)
|
411
|
-
|
625
|
+
|
626
|
+
jobs.dup.select do |job|
|
412
627
|
job_class = job.fetch(:job)
|
628
|
+
|
413
629
|
if only
|
414
|
-
next false unless
|
630
|
+
next false unless filter_as_proc(only).call(job)
|
415
631
|
elsif except
|
416
|
-
next false if
|
632
|
+
next false if filter_as_proc(except).call(job)
|
417
633
|
end
|
634
|
+
|
418
635
|
if queue
|
419
636
|
next false unless queue.to_s == job.fetch(:queue, job_class.queue_name)
|
420
637
|
end
|
638
|
+
|
639
|
+
if at && job[:at]
|
640
|
+
next false if job[:at] > at.to_f
|
641
|
+
end
|
642
|
+
|
643
|
+
yield job if block_given?
|
644
|
+
|
421
645
|
true
|
422
646
|
end
|
423
647
|
end
|
424
648
|
|
649
|
+
def filter_as_proc(filter)
|
650
|
+
return filter if filter.is_a?(Proc)
|
651
|
+
|
652
|
+
->(job) { Array(filter).include?(job.fetch(:job)) }
|
653
|
+
end
|
654
|
+
|
655
|
+
def enqueued_jobs_with(only: nil, except: nil, queue: nil, at: nil, &block)
|
656
|
+
jobs_with(enqueued_jobs, only: only, except: except, queue: queue, at: at, &block)
|
657
|
+
end
|
658
|
+
|
659
|
+
def performed_jobs_with(only: nil, except: nil, queue: nil, &block)
|
660
|
+
jobs_with(performed_jobs, only: only, except: except, queue: queue, &block)
|
661
|
+
end
|
662
|
+
|
663
|
+
def flush_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil)
|
664
|
+
enqueued_jobs_with(only: only, except: except, queue: queue, at: at) do |payload|
|
665
|
+
queue_adapter.enqueued_jobs.delete(payload)
|
666
|
+
queue_adapter.performed_jobs << payload
|
667
|
+
instantiate_job(payload).perform_now
|
668
|
+
end.count
|
669
|
+
end
|
670
|
+
|
425
671
|
def prepare_args_for_assertion(args)
|
426
672
|
args.dup.tap do |arguments|
|
427
|
-
|
673
|
+
if arguments[:at].acts_like?(:time)
|
674
|
+
at_range = arguments[:at] - 1..arguments[:at] + 1
|
675
|
+
arguments[:at] = ->(at) { at_range.cover?(at) }
|
676
|
+
end
|
428
677
|
end
|
429
678
|
end
|
430
679
|
|
431
680
|
def deserialize_args_for_assertion(job)
|
432
681
|
job.dup.tap do |new_job|
|
682
|
+
new_job[:at] = Time.at(new_job[:at]) if new_job[:at]
|
433
683
|
new_job[:args] = ActiveJob::Arguments.deserialize(new_job[:args]) if new_job[:args]
|
434
684
|
end
|
435
685
|
end
|
436
686
|
|
437
687
|
def instantiate_job(payload)
|
438
|
-
|
439
|
-
job = payload[:job].new(*args)
|
688
|
+
job = payload[:job].deserialize(payload)
|
440
689
|
job.scheduled_at = Time.at(payload[:at]) if payload.key?(:at)
|
441
|
-
job.
|
690
|
+
job.send(:deserialize_arguments_if_needed)
|
442
691
|
job
|
443
692
|
end
|
444
693
|
|
data/lib/active_job.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c) 2014-
|
4
|
+
# Copyright (c) 2014-2022 David Heinemeier Hansson
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
@@ -33,6 +33,7 @@ module ActiveJob
|
|
33
33
|
|
34
34
|
autoload :Base
|
35
35
|
autoload :QueueAdapters
|
36
|
+
autoload :Serializers
|
36
37
|
autoload :ConfiguredJob
|
37
38
|
autoload :TestCase
|
38
39
|
autoload :TestHelper
|