activejob 5.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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