activejob 5.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +80 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.md +126 -0
  5. data/lib/active_job.rb +39 -0
  6. data/lib/active_job/arguments.rb +165 -0
  7. data/lib/active_job/base.rb +74 -0
  8. data/lib/active_job/callbacks.rb +155 -0
  9. data/lib/active_job/configured_job.rb +18 -0
  10. data/lib/active_job/core.rb +158 -0
  11. data/lib/active_job/enqueuing.rb +59 -0
  12. data/lib/active_job/exceptions.rb +134 -0
  13. data/lib/active_job/execution.rb +49 -0
  14. data/lib/active_job/gem_version.rb +17 -0
  15. data/lib/active_job/logging.rb +130 -0
  16. data/lib/active_job/queue_adapter.rb +60 -0
  17. data/lib/active_job/queue_adapters.rb +139 -0
  18. data/lib/active_job/queue_adapters/async_adapter.rb +116 -0
  19. data/lib/active_job/queue_adapters/backburner_adapter.rb +36 -0
  20. data/lib/active_job/queue_adapters/delayed_job_adapter.rb +47 -0
  21. data/lib/active_job/queue_adapters/inline_adapter.rb +23 -0
  22. data/lib/active_job/queue_adapters/qu_adapter.rb +46 -0
  23. data/lib/active_job/queue_adapters/que_adapter.rb +39 -0
  24. data/lib/active_job/queue_adapters/queue_classic_adapter.rb +58 -0
  25. data/lib/active_job/queue_adapters/resque_adapter.rb +53 -0
  26. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +47 -0
  27. data/lib/active_job/queue_adapters/sneakers_adapter.rb +48 -0
  28. data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +49 -0
  29. data/lib/active_job/queue_adapters/test_adapter.rb +67 -0
  30. data/lib/active_job/queue_name.rb +49 -0
  31. data/lib/active_job/queue_priority.rb +43 -0
  32. data/lib/active_job/railtie.rb +34 -0
  33. data/lib/active_job/test_case.rb +11 -0
  34. data/lib/active_job/test_helper.rb +456 -0
  35. data/lib/active_job/translation.rb +13 -0
  36. data/lib/active_job/version.rb +10 -0
  37. data/lib/rails/generators/job/job_generator.rb +40 -0
  38. data/lib/rails/generators/job/templates/application_job.rb.tt +9 -0
  39. data/lib/rails/generators/job/templates/job.rb.tt +9 -0
  40. metadata +110 -0
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module QueueAdapters
5
+ # == Test adapter for Active Job
6
+ #
7
+ # The test adapter should be used only in testing. Along with
8
+ # <tt>ActiveJob::TestCase</tt> and <tt>ActiveJob::TestHelper</tt>
9
+ # it makes a great tool to test your Rails application.
10
+ #
11
+ # To use the test adapter set queue_adapter config to +:test+.
12
+ #
13
+ # Rails.application.config.active_job.queue_adapter = :test
14
+ class TestAdapter
15
+ attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter, :reject)
16
+ attr_writer(:enqueued_jobs, :performed_jobs)
17
+
18
+ # Provides a store of all the enqueued jobs with the TestAdapter so you can check them.
19
+ def enqueued_jobs
20
+ @enqueued_jobs ||= []
21
+ end
22
+
23
+ # Provides a store of all the performed jobs with the TestAdapter so you can check them.
24
+ def performed_jobs
25
+ @performed_jobs ||= []
26
+ end
27
+
28
+ def enqueue(job) #:nodoc:
29
+ return if filtered?(job)
30
+
31
+ job_data = job_to_hash(job)
32
+ enqueue_or_perform(perform_enqueued_jobs, job, job_data)
33
+ end
34
+
35
+ def enqueue_at(job, timestamp) #:nodoc:
36
+ return if filtered?(job)
37
+
38
+ job_data = job_to_hash(job, at: timestamp)
39
+ enqueue_or_perform(perform_enqueued_at_jobs, job, job_data)
40
+ end
41
+
42
+ private
43
+ def job_to_hash(job, extras = {})
44
+ { job: job.class, args: job.serialize.fetch("arguments"), queue: job.queue_name }.merge!(extras)
45
+ end
46
+
47
+ def enqueue_or_perform(perform, job, job_data)
48
+ if perform
49
+ performed_jobs << job_data
50
+ Base.execute job.serialize
51
+ else
52
+ enqueued_jobs << job_data
53
+ end
54
+ end
55
+
56
+ def filtered?(job)
57
+ if filter
58
+ !Array(filter).include?(job.class)
59
+ elsif reject
60
+ Array(reject).include?(job.class)
61
+ else
62
+ false
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module QueueName
5
+ extend ActiveSupport::Concern
6
+
7
+ # Includes the ability to override the default queue name and prefix.
8
+ module ClassMethods
9
+ mattr_accessor :queue_name_prefix
10
+ mattr_accessor :default_queue_name, default: "default"
11
+
12
+ # Specifies the name of the queue to process the job on.
13
+ #
14
+ # class PublishToFeedJob < ActiveJob::Base
15
+ # queue_as :feeds
16
+ #
17
+ # def perform(post)
18
+ # post.to_feed!
19
+ # end
20
+ # end
21
+ def queue_as(part_name = nil, &block)
22
+ if block_given?
23
+ self.queue_name = block
24
+ else
25
+ self.queue_name = queue_name_from_part(part_name)
26
+ end
27
+ end
28
+
29
+ def queue_name_from_part(part_name) #:nodoc:
30
+ queue_name = part_name || default_queue_name
31
+ name_parts = [queue_name_prefix.presence, queue_name]
32
+ name_parts.compact.join(queue_name_delimiter)
33
+ end
34
+ end
35
+
36
+ included do
37
+ class_attribute :queue_name, instance_accessor: false, default: default_queue_name
38
+ class_attribute :queue_name_delimiter, instance_accessor: false, default: "_"
39
+ end
40
+
41
+ # Returns the name of the queue the job will be run on.
42
+ def queue_name
43
+ if @queue_name.is_a?(Proc)
44
+ @queue_name = self.class.queue_name_from_part(instance_exec(&@queue_name))
45
+ end
46
+ @queue_name
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module QueuePriority
5
+ extend ActiveSupport::Concern
6
+
7
+ # Includes the ability to override the default queue priority.
8
+ module ClassMethods
9
+ mattr_accessor :default_priority
10
+
11
+ # Specifies the priority of the queue to create the job with.
12
+ #
13
+ # class PublishToFeedJob < ActiveJob::Base
14
+ # queue_with_priority 50
15
+ #
16
+ # def perform(post)
17
+ # post.to_feed!
18
+ # end
19
+ # end
20
+ #
21
+ # Specify either an argument or a block.
22
+ def queue_with_priority(priority = nil, &block)
23
+ if block_given?
24
+ self.priority = block
25
+ else
26
+ self.priority = priority
27
+ end
28
+ end
29
+ end
30
+
31
+ included do
32
+ class_attribute :priority, instance_accessor: false, default: 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
+ end
43
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "global_id/railtie"
4
+ require "active_job"
5
+
6
+ module ActiveJob
7
+ # = Active Job Railtie
8
+ class Railtie < Rails::Railtie # :nodoc:
9
+ config.active_job = ActiveSupport::OrderedOptions.new
10
+
11
+ initializer "active_job.logger" do
12
+ ActiveSupport.on_load(:active_job) { self.logger = ::Rails.logger }
13
+ end
14
+
15
+ initializer "active_job.set_configs" do |app|
16
+ options = app.config.active_job
17
+ options.queue_adapter ||= :async
18
+
19
+ ActiveSupport.on_load(:active_job) do
20
+ options.each { |k, v| send("#{k}=", v) }
21
+ end
22
+ end
23
+
24
+ initializer "active_job.set_reloader_hook" do |app|
25
+ ActiveSupport.on_load(:active_job) do
26
+ ActiveJob::Callbacks.singleton_class.set_callback(:execute, :around, prepend: true) do |_, inner|
27
+ app.reloader.wrap do
28
+ inner.call
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/test_case"
4
+
5
+ module ActiveJob
6
+ class TestCase < ActiveSupport::TestCase
7
+ include ActiveJob::TestHelper
8
+
9
+ ActiveSupport.run_load_hooks(:active_job_test_case, self)
10
+ end
11
+ end
@@ -0,0 +1,456 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/class/subclasses"
4
+ require "active_support/core_ext/hash/keys"
5
+
6
+ module ActiveJob
7
+ # Provides helper methods for testing Active Job
8
+ module TestHelper
9
+ delegate :enqueued_jobs, :enqueued_jobs=,
10
+ :performed_jobs, :performed_jobs=,
11
+ to: :queue_adapter
12
+
13
+ module TestQueueAdapter
14
+ extend ActiveSupport::Concern
15
+
16
+ included do
17
+ class_attribute :_test_adapter, instance_accessor: false, instance_predicate: false
18
+ end
19
+
20
+ module ClassMethods
21
+ def queue_adapter
22
+ self._test_adapter.nil? ? super : self._test_adapter
23
+ end
24
+
25
+ def disable_test_adapter
26
+ self._test_adapter = nil
27
+ end
28
+
29
+ def enable_test_adapter(test_adapter)
30
+ self._test_adapter = test_adapter
31
+ end
32
+ end
33
+ end
34
+
35
+ ActiveJob::Base.include(TestQueueAdapter)
36
+
37
+ def before_setup # :nodoc:
38
+ test_adapter = queue_adapter_for_test
39
+
40
+ queue_adapter_changed_jobs.each do |klass|
41
+ klass.enable_test_adapter(test_adapter)
42
+ end
43
+
44
+ clear_enqueued_jobs
45
+ clear_performed_jobs
46
+ super
47
+ end
48
+
49
+ def after_teardown # :nodoc:
50
+ super
51
+
52
+ queue_adapter_changed_jobs.each { |klass| klass.disable_test_adapter }
53
+ end
54
+
55
+ # Specifies the queue adapter to use with all active job test helpers.
56
+ #
57
+ # Returns an instance of the queue adapter and defaults to
58
+ # <tt>ActiveJob::QueueAdapters::TestAdapter</tt>.
59
+ #
60
+ # Note: The adapter provided by this method must provide some additional
61
+ # methods from those expected of a standard <tt>ActiveJob::QueueAdapter</tt>
62
+ # in order to be used with the active job test helpers. Refer to
63
+ # <tt>ActiveJob::QueueAdapters::TestAdapter</tt>.
64
+ def queue_adapter_for_test
65
+ ActiveJob::QueueAdapters::TestAdapter.new
66
+ end
67
+
68
+ # Asserts that the number of enqueued jobs matches the given number.
69
+ #
70
+ # def test_jobs
71
+ # assert_enqueued_jobs 0
72
+ # HelloJob.perform_later('david')
73
+ # assert_enqueued_jobs 1
74
+ # HelloJob.perform_later('abdelkader')
75
+ # assert_enqueued_jobs 2
76
+ # end
77
+ #
78
+ # If a block is passed, that block will cause the specified number of
79
+ # jobs to be enqueued.
80
+ #
81
+ # def test_jobs_again
82
+ # assert_enqueued_jobs 1 do
83
+ # HelloJob.perform_later('cristian')
84
+ # end
85
+ #
86
+ # assert_enqueued_jobs 2 do
87
+ # HelloJob.perform_later('aaron')
88
+ # HelloJob.perform_later('rafael')
89
+ # end
90
+ # end
91
+ #
92
+ # The number of times a specific job was enqueued can be asserted.
93
+ #
94
+ # def test_logging_job
95
+ # assert_enqueued_jobs 1, only: LoggingJob do
96
+ # LoggingJob.perform_later
97
+ # HelloJob.perform_later('jeremy')
98
+ # end
99
+ # end
100
+ #
101
+ # The number of times a job except specific class was enqueued can be asserted.
102
+ #
103
+ # def test_logging_job
104
+ # assert_enqueued_jobs 1, except: HelloJob do
105
+ # LoggingJob.perform_later
106
+ # HelloJob.perform_later('jeremy')
107
+ # end
108
+ # end
109
+ #
110
+ # The number of times a job is enqueued to a specific queue can also be asserted.
111
+ #
112
+ # def test_logging_job
113
+ # assert_enqueued_jobs 2, queue: 'default' do
114
+ # LoggingJob.perform_later
115
+ # HelloJob.perform_later('elfassy')
116
+ # end
117
+ # end
118
+ def assert_enqueued_jobs(number, only: nil, except: nil, queue: nil)
119
+ if block_given?
120
+ original_count = enqueued_jobs_size(only: only, except: except, queue: queue)
121
+ yield
122
+ new_count = enqueued_jobs_size(only: only, except: except, queue: queue)
123
+ assert_equal number, new_count - original_count, "#{number} jobs expected, but #{new_count - original_count} were enqueued"
124
+ else
125
+ actual_count = enqueued_jobs_size(only: only, except: except, queue: queue)
126
+ assert_equal number, actual_count, "#{number} jobs expected, but #{actual_count} were enqueued"
127
+ end
128
+ end
129
+
130
+ # Asserts that no jobs have been enqueued.
131
+ #
132
+ # def test_jobs
133
+ # assert_no_enqueued_jobs
134
+ # HelloJob.perform_later('jeremy')
135
+ # assert_enqueued_jobs 1
136
+ # end
137
+ #
138
+ # If a block is passed, that block should not cause any job to be enqueued.
139
+ #
140
+ # def test_jobs_again
141
+ # assert_no_enqueued_jobs do
142
+ # # No job should be enqueued from this block
143
+ # end
144
+ # end
145
+ #
146
+ # It can be asserted that no jobs of a specific kind are enqueued:
147
+ #
148
+ # def test_no_logging
149
+ # assert_no_enqueued_jobs only: LoggingJob do
150
+ # HelloJob.perform_later('jeremy')
151
+ # end
152
+ # end
153
+ #
154
+ # It can be asserted that no jobs except specific class are enqueued:
155
+ #
156
+ # def test_no_logging
157
+ # assert_no_enqueued_jobs except: HelloJob do
158
+ # HelloJob.perform_later('jeremy')
159
+ # end
160
+ # end
161
+ #
162
+ # Note: This assertion is simply a shortcut for:
163
+ #
164
+ # 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
167
+ end
168
+
169
+ # Asserts that the number of performed jobs matches the given number.
170
+ # If no block is passed, <tt>perform_enqueued_jobs</tt>
171
+ # must be called around the job call.
172
+ #
173
+ # def test_jobs
174
+ # assert_performed_jobs 0
175
+ #
176
+ # perform_enqueued_jobs do
177
+ # HelloJob.perform_later('xavier')
178
+ # end
179
+ # assert_performed_jobs 1
180
+ #
181
+ # perform_enqueued_jobs do
182
+ # HelloJob.perform_later('yves')
183
+ # assert_performed_jobs 2
184
+ # end
185
+ # end
186
+ #
187
+ # If a block is passed, that block should cause the specified number of
188
+ # jobs to be performed.
189
+ #
190
+ # def test_jobs_again
191
+ # assert_performed_jobs 1 do
192
+ # HelloJob.perform_later('robin')
193
+ # end
194
+ #
195
+ # assert_performed_jobs 2 do
196
+ # HelloJob.perform_later('carlos')
197
+ # HelloJob.perform_later('sean')
198
+ # end
199
+ # end
200
+ #
201
+ # The block form supports filtering. If the :only option is specified,
202
+ # then only the listed job(s) will be performed.
203
+ #
204
+ # def test_hello_job
205
+ # assert_performed_jobs 1, only: HelloJob do
206
+ # HelloJob.perform_later('jeremy')
207
+ # LoggingJob.perform_later
208
+ # end
209
+ # end
210
+ #
211
+ # Also if the :except option is specified,
212
+ # then the job(s) except specific class will be performed.
213
+ #
214
+ # def test_hello_job
215
+ # assert_performed_jobs 1, except: LoggingJob do
216
+ # HelloJob.perform_later('jeremy')
217
+ # LoggingJob.perform_later
218
+ # end
219
+ # end
220
+ #
221
+ # An array may also be specified, to support testing multiple jobs.
222
+ #
223
+ # def test_hello_and_logging_jobs
224
+ # assert_nothing_raised do
225
+ # assert_performed_jobs 2, only: [HelloJob, LoggingJob] do
226
+ # HelloJob.perform_later('jeremy')
227
+ # LoggingJob.perform_later('stewie')
228
+ # RescueJob.perform_later('david')
229
+ # end
230
+ # end
231
+ # end
232
+ def assert_performed_jobs(number, only: nil, except: nil)
233
+ if block_given?
234
+ original_count = performed_jobs.size
235
+ perform_enqueued_jobs(only: only, except: except) { yield }
236
+ new_count = performed_jobs.size
237
+ assert_equal number, new_count - original_count,
238
+ "#{number} jobs expected, but #{new_count - original_count} were performed"
239
+ else
240
+ performed_jobs_size = performed_jobs.size
241
+ assert_equal number, performed_jobs_size, "#{number} jobs expected, but #{performed_jobs_size} were performed"
242
+ end
243
+ end
244
+
245
+ # Asserts that no jobs have been performed.
246
+ #
247
+ # def test_jobs
248
+ # assert_no_performed_jobs
249
+ #
250
+ # perform_enqueued_jobs do
251
+ # HelloJob.perform_later('matthew')
252
+ # assert_performed_jobs 1
253
+ # end
254
+ # end
255
+ #
256
+ # If a block is passed, that block should not cause any job to be performed.
257
+ #
258
+ # def test_jobs_again
259
+ # assert_no_performed_jobs do
260
+ # # No job should be performed from this block
261
+ # end
262
+ # end
263
+ #
264
+ # The block form supports filtering. If the :only option is specified,
265
+ # then only the listed job(s) will not be performed.
266
+ #
267
+ # def test_no_logging
268
+ # assert_no_performed_jobs only: LoggingJob do
269
+ # HelloJob.perform_later('jeremy')
270
+ # end
271
+ # end
272
+ #
273
+ # Also if the :except option is specified,
274
+ # then the job(s) except specific class will not be performed.
275
+ #
276
+ # def test_no_logging
277
+ # assert_no_performed_jobs except: HelloJob do
278
+ # HelloJob.perform_later('jeremy')
279
+ # end
280
+ # end
281
+ #
282
+ # Note: This assertion is simply a shortcut for:
283
+ #
284
+ # 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
287
+ end
288
+
289
+ # Asserts that the job passed in the block has been enqueued with the given arguments.
290
+ #
291
+ # def test_assert_enqueued_with
292
+ # assert_enqueued_with(job: MyJob, args: [1,2,3], queue: 'low') do
293
+ # MyJob.perform_later(1,2,3)
294
+ # end
295
+ #
296
+ # assert_enqueued_with(job: MyJob, at: Date.tomorrow.noon) do
297
+ # MyJob.set(wait_until: Date.tomorrow.noon).perform_later
298
+ # end
299
+ # end
300
+ def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil)
301
+ original_enqueued_jobs_count = enqueued_jobs.count
302
+ expected = { job: job, args: args, at: at, queue: queue }.compact
303
+ expected_args = prepare_args_for_assertion(expected)
304
+ yield
305
+ in_block_jobs = enqueued_jobs.drop(original_enqueued_jobs_count)
306
+ matching_job = in_block_jobs.find do |in_block_job|
307
+ deserialized_job = deserialize_args_for_assertion(in_block_job)
308
+ expected_args.all? { |key, value| value == deserialized_job[key] }
309
+ end
310
+ assert matching_job, "No enqueued job found with #{expected}"
311
+ instantiate_job(matching_job)
312
+ end
313
+
314
+ # Asserts that the job passed in the block has been performed with the given arguments.
315
+ #
316
+ # def test_assert_performed_with
317
+ # assert_performed_with(job: MyJob, args: [1,2,3], queue: 'high') do
318
+ # MyJob.perform_later(1,2,3)
319
+ # end
320
+ #
321
+ # assert_performed_with(job: MyJob, at: Date.tomorrow.noon) do
322
+ # MyJob.set(wait_until: Date.tomorrow.noon).perform_later
323
+ # end
324
+ # end
325
+ def assert_performed_with(job: nil, args: nil, at: nil, queue: nil)
326
+ original_performed_jobs_count = performed_jobs.count
327
+ expected = { job: job, args: args, at: at, queue: queue }.compact
328
+ expected_args = prepare_args_for_assertion(expected)
329
+ perform_enqueued_jobs { yield }
330
+ in_block_jobs = performed_jobs.drop(original_performed_jobs_count)
331
+ matching_job = in_block_jobs.find do |in_block_job|
332
+ deserialized_job = deserialize_args_for_assertion(in_block_job)
333
+ expected_args.all? { |key, value| value == deserialized_job[key] }
334
+ end
335
+ assert matching_job, "No performed job found with #{expected}"
336
+ instantiate_job(matching_job)
337
+ end
338
+
339
+ # Performs all enqueued jobs in the duration of the block.
340
+ #
341
+ # def test_perform_enqueued_jobs
342
+ # perform_enqueued_jobs do
343
+ # MyJob.perform_later(1, 2, 3)
344
+ # end
345
+ # assert_performed_jobs 1
346
+ # end
347
+ #
348
+ # This method also supports filtering. If the +:only+ option is specified,
349
+ # then only the listed job(s) will be performed.
350
+ #
351
+ # def test_perform_enqueued_jobs_with_only
352
+ # perform_enqueued_jobs(only: MyJob) do
353
+ # MyJob.perform_later(1, 2, 3) # will be performed
354
+ # HelloJob.perform_later(1, 2, 3) # will not be performed
355
+ # end
356
+ # assert_performed_jobs 1
357
+ # end
358
+ #
359
+ # Also if the +:except+ option is specified,
360
+ # then the job(s) except specific class will be performed.
361
+ #
362
+ # def test_perform_enqueued_jobs_with_except
363
+ # perform_enqueued_jobs(except: HelloJob) do
364
+ # MyJob.perform_later(1, 2, 3) # will be performed
365
+ # HelloJob.perform_later(1, 2, 3) # will not be performed
366
+ # end
367
+ # assert_performed_jobs 1
368
+ # end
369
+ #
370
+ def perform_enqueued_jobs(only: nil, except: nil)
371
+ validate_option(only: only, except: except)
372
+ old_perform_enqueued_jobs = queue_adapter.perform_enqueued_jobs
373
+ old_perform_enqueued_at_jobs = queue_adapter.perform_enqueued_at_jobs
374
+ old_filter = queue_adapter.filter
375
+ old_reject = queue_adapter.reject
376
+
377
+ begin
378
+ queue_adapter.perform_enqueued_jobs = true
379
+ queue_adapter.perform_enqueued_at_jobs = true
380
+ queue_adapter.filter = only
381
+ queue_adapter.reject = except
382
+ yield
383
+ ensure
384
+ queue_adapter.perform_enqueued_jobs = old_perform_enqueued_jobs
385
+ queue_adapter.perform_enqueued_at_jobs = old_perform_enqueued_at_jobs
386
+ queue_adapter.filter = old_filter
387
+ queue_adapter.reject = old_reject
388
+ end
389
+ end
390
+
391
+ # Accesses the queue_adapter set by ActiveJob::Base.
392
+ #
393
+ # def test_assert_job_has_custom_queue_adapter_set
394
+ # assert_instance_of CustomQueueAdapter, HelloJob.queue_adapter
395
+ # end
396
+ def queue_adapter
397
+ ActiveJob::Base.queue_adapter
398
+ end
399
+
400
+ private
401
+ def clear_enqueued_jobs
402
+ enqueued_jobs.clear
403
+ end
404
+
405
+ def clear_performed_jobs
406
+ performed_jobs.clear
407
+ end
408
+
409
+ def enqueued_jobs_size(only: nil, except: nil, queue: nil)
410
+ validate_option(only: only, except: except)
411
+ enqueued_jobs.count do |job|
412
+ job_class = job.fetch(:job)
413
+ if only
414
+ next false unless Array(only).include?(job_class)
415
+ elsif except
416
+ next false if Array(except).include?(job_class)
417
+ end
418
+ if queue
419
+ next false unless queue.to_s == job.fetch(:queue, job_class.queue_name)
420
+ end
421
+ true
422
+ end
423
+ end
424
+
425
+ def prepare_args_for_assertion(args)
426
+ args.dup.tap do |arguments|
427
+ arguments[:at] = arguments[:at].to_f if arguments[:at]
428
+ end
429
+ end
430
+
431
+ def deserialize_args_for_assertion(job)
432
+ job.dup.tap do |new_job|
433
+ new_job[:args] = ActiveJob::Arguments.deserialize(new_job[:args]) if new_job[:args]
434
+ end
435
+ end
436
+
437
+ def instantiate_job(payload)
438
+ args = ActiveJob::Arguments.deserialize(payload[:args])
439
+ job = payload[:job].new(*args)
440
+ job.scheduled_at = Time.at(payload[:at]) if payload.key?(:at)
441
+ job.queue_name = payload[:queue]
442
+ job
443
+ end
444
+
445
+ def queue_adapter_changed_jobs
446
+ (ActiveJob::Base.descendants << ActiveJob::Base).select do |klass|
447
+ # only override explicitly set adapters, a quirk of `class_attribute`
448
+ klass.singleton_class.public_instance_methods(false).include?(:_queue_adapter)
449
+ end
450
+ end
451
+
452
+ def validate_option(only: nil, except: nil)
453
+ raise ArgumentError, "Cannot specify both `:only` and `:except` options." if only && except
454
+ end
455
+ end
456
+ end