activejob 7.1.5.1 → 7.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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -248
  3. data/README.md +1 -1
  4. data/lib/active_job/arguments.rb +0 -11
  5. data/lib/active_job/base.rb +2 -2
  6. data/lib/active_job/callbacks.rb +0 -3
  7. data/lib/active_job/configured_job.rb +0 -4
  8. data/lib/active_job/core.rb +4 -19
  9. data/lib/active_job/enqueue_after_transaction_commit.rb +28 -0
  10. data/lib/active_job/enqueuing.rb +42 -11
  11. data/lib/active_job/exceptions.rb +7 -12
  12. data/lib/active_job/gem_version.rb +3 -3
  13. data/lib/active_job/log_subscriber.rb +2 -2
  14. data/lib/active_job/logging.rb +16 -2
  15. data/lib/active_job/queue_adapter.rb +5 -4
  16. data/lib/active_job/queue_adapters/abstract_adapter.rb +27 -0
  17. data/lib/active_job/queue_adapters/async_adapter.rb +1 -1
  18. data/lib/active_job/queue_adapters/backburner_adapter.rb +1 -1
  19. data/lib/active_job/queue_adapters/delayed_job_adapter.rb +9 -1
  20. data/lib/active_job/queue_adapters/inline_adapter.rb +5 -1
  21. data/lib/active_job/queue_adapters/queue_classic_adapter.rb +9 -1
  22. data/lib/active_job/queue_adapters/resque_adapter.rb +1 -1
  23. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +1 -1
  24. data/lib/active_job/queue_adapters/sneakers_adapter.rb +1 -1
  25. data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +1 -1
  26. data/lib/active_job/queue_adapters/test_adapter.rb +10 -2
  27. data/lib/active_job/queue_adapters.rb +1 -0
  28. data/lib/active_job/railtie.rb +13 -1
  29. data/lib/active_job/serializers/object_serializer.rb +2 -0
  30. data/lib/active_job/test_helper.rb +28 -5
  31. data/lib/active_job.rb +13 -8
  32. metadata +11 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3163adeb0ad6bf21b0048cfcde214b97af34a0b49299f37cd2e93905a5839327
4
- data.tar.gz: ccaff11c2aa436b1ad0b7a479c030c7e241ee8e2c0a4754361ac6acb6a703d5f
3
+ metadata.gz: 4f76db92910f325154aa9d955728c51e2707232f2db258198ef3128d3f07ad26
4
+ data.tar.gz: 3c68ce1d7ff44d94a9c877923e8f82de2f747d1a889e57c2bed0bd4fc71a41d5
5
5
  SHA512:
6
- metadata.gz: d319ffd95f49cddec8a0fdbc39f36d5029a3d7bc91086564cd673f784268a86d20c3d2977d248a8f7591e80d8652be11d9c9bd0e94afb5cbefad132035d1ad68
7
- data.tar.gz: e9eaebe18fc732613af2da14a35d5993f1c4c6e87ff01908fef6f569c51c395150046d1502d913df2bcb4cbeb0c2810bbe2d5a337f8903207e604dabba789509
6
+ metadata.gz: 8af4d3675c132bf94582a852445b7aca33b7fdd44bea30c17e6ac7823c12c5d8857e712dc7f487ce1f5ab2fec1445bd94b0556aad19af66ccf6c5190c7c9f3e8
7
+ data.tar.gz: 3560f91b6101294422260c4dfa4106d6588fccd7aa7b8ef94eaa3fbbf17b5380001ed6667d0619a68a6258612193c1677dd5e7e3a1613f9d1ff21368562687e8
data/CHANGELOG.md CHANGED
@@ -1,310 +1,111 @@
1
- ## Rails 7.1.5.1 (December 10, 2024) ##
2
-
3
- * No changes.
1
+ ## Rails 7.2.3 (October 28, 2025) ##
4
2
 
3
+ * Include the actual Active Job locale when serializing rather than I18n locale.
5
4
 
6
- ## Rails 7.1.5 (October 30, 2024) ##
5
+ *Adrien S*
7
6
 
8
- * No changes.
7
+ * Avoid crashing in Active Job logger when logging enqueueing errors
9
8
 
9
+ `ActiveJob.perform_all_later` could fail with a `TypeError` when all
10
+ provided jobs failed to be enqueueed.
10
11
 
11
- ## Rails 7.1.4.2 (October 23, 2024) ##
12
+ *Efstathios Stivaros*
12
13
 
13
- * No changes.
14
14
 
15
-
16
- ## Rails 7.1.4.1 (October 15, 2024) ##
15
+ ## Rails 7.2.2.2 (August 13, 2025) ##
17
16
 
18
17
  * No changes.
19
18
 
20
19
 
21
- ## Rails 7.1.4 (August 22, 2024) ##
22
-
23
- * Register autoload for `ActiveJob::Arguments`.
24
-
25
- *Rafael Mendonça França*
26
-
27
-
28
- ## Rails 7.1.3.4 (June 04, 2024) ##
20
+ ## Rails 7.2.2.1 (December 10, 2024) ##
29
21
 
30
22
  * No changes.
31
23
 
32
24
 
33
- ## Rails 7.1.3.3 (May 16, 2024) ##
25
+ ## Rails 7.2.2 (October 30, 2024) ##
34
26
 
35
27
  * No changes.
36
28
 
37
29
 
38
- ## Rails 7.1.3.2 (February 21, 2024) ##
30
+ ## Rails 7.2.1.2 (October 23, 2024) ##
39
31
 
40
32
  * No changes.
41
33
 
42
34
 
43
- ## Rails 7.1.3.1 (February 21, 2024) ##
35
+ ## Rails 7.2.1.1 (October 15, 2024) ##
44
36
 
45
37
  * No changes.
46
38
 
47
39
 
48
- ## Rails 7.1.3 (January 16, 2024) ##
49
-
50
- * Do not trigger immediate loading of `ActiveJob::Base` when loading `ActiveJob::TestHelper`.
51
-
52
- *Maxime Réty*
53
-
54
- * Preserve the serialized timezone when deserializing `ActiveSupport::TimeWithZone` arguments.
55
-
56
- *Joshua Young*
57
-
58
- * Fix ActiveJob arguments serialization to correctly serialize String subclasses having custom serializers.
59
-
60
- *fatkodima*
61
-
62
-
63
- ## Rails 7.1.2 (November 10, 2023) ##
40
+ ## Rails 7.2.1 (August 22, 2024) ##
64
41
 
65
42
  * No changes.
66
43
 
67
44
 
68
- ## Rails 7.1.1 (October 11, 2023) ##
69
-
70
- * Don't log enqueuing details when the job wasn't enqueued.
71
-
72
- *Dustin Brown*
73
-
74
-
75
- ## Rails 7.1.0 (October 05, 2023) ##
76
-
77
- * No changes.
78
-
79
-
80
- ## Rails 7.1.0.rc2 (October 01, 2023) ##
81
-
82
- * Make sure `scheduled_at` is a Time object when asserting enqueued jobs.
83
-
84
- *Rafael Mendonça França*
85
-
86
-
87
- ## Rails 7.1.0.rc1 (September 27, 2023) ##
88
-
89
- * Set `scheduled_at` attribute as a Time object instead of epoch seconds, and serialize and deserialize the value
90
- when enqueued. Assigning a numeric/epoch value to scheduled_at= is deprecated; use a Time object instead.
91
-
92
- Deserializes `enqueued_at` as a Time instead of ISO8601 String.
93
-
94
- *Ben Sheldon*
95
-
96
- * Clarify the backoff strategy for the recommended `:wait` option when retrying jobs
97
-
98
- `wait: :exponentially_longer` is waiting polynomially longer, so it is now recommended to use `wait: :polynomially_longer` to keep the same behavior.
99
-
100
- *Victor Mours*
101
-
102
-
103
- ## Rails 7.1.0.beta1 (September 13, 2023) ##
104
-
105
- * Fix Active Job log message to correctly report a job failed to enqueue
106
- when the adapter raises an `ActiveJob::EnqueueError`.
107
-
108
- *Ben Sheldon*
109
-
110
- * Add `after_discard` method.
111
-
112
- This method lets job authors define a block which will be run when a job is about to be discarded. For example:
113
-
114
- ```ruby
115
- class AfterDiscardJob < ActiveJob::Base
116
- after_discard do |job, exception|
117
- Rails.logger.info("#{job.class} raised an exception: #{exception}")
118
- end
119
-
120
- def perform
121
- raise StandardError
122
- end
123
- end
124
- ```
125
-
126
- The above job will run the block passed to `after_discard` after the job is discarded. The exception will
127
- still be raised after the block has been run.
128
-
129
- *Rob Cardy*
130
-
131
- * Fix deserialization of ActiveSupport::Duration
132
-
133
- Previously, a deserialized Duration would return an array from Duration#parts.
134
- It will now return a hash just like a regular Duration.
45
+ ## Rails 7.2.0 (August 09, 2024) ##
135
46
 
136
- This also fixes an error when trying to add or subtract from a deserialized Duration
137
- (eg `duration + 1.year`).
47
+ * All tests now respect the `active_job.queue_adapter` config.
138
48
 
139
- *Jonathan del Strother*
49
+ Previously if you had set `config.active_job.queue_adapter` in your `config/application.rb`
50
+ or `config/environments/test.rb` file, the adapter you selected was previously not used consistently
51
+ across all tests. In some tests your adapter would be used, but other tests would use the `TestAdapter`.
140
52
 
141
- * `perform_enqueued_jobs` is now compatible with all Active Job adapters
53
+ In Rails 7.2, all tests will respect the `queue_adapter` config if provided. If no config is provided,
54
+ the `TestAdapter` will continue to be used.
142
55
 
143
- This means that methods that depend on it, like Action Mailer's `assert_emails`,
144
- will work correctly even if the test adapter is not used.
56
+ See [#48585](https://github.com/rails/rails/pull/48585) for more details.
145
57
 
146
58
  *Alex Ghiculescu*
147
59
 
148
- * Allow queue adapters to provide a custom name by implementing `queue_adapter_name`
60
+ * Make Active Job transaction aware when used conjointly with Active Record.
149
61
 
150
- *Sander Verdonschot*
151
-
152
- * Log background job enqueue callers
153
-
154
- Add `verbose_enqueue_logs` configuration option to display the caller
155
- of background job enqueue in the log to help with debugging.
156
-
157
- Example log line:
158
-
159
- ```
160
- Enqueued AvatarThumbnailsJob (Job ID: ab528951-41fb-4c48-9129-3171791c27d6) to Sidekiq(default) with arguments: 1092412064
161
- ↳ app/models/user.rb:421:in `generate_avatar_thumbnails'
162
- ```
163
-
164
- Enabled in development only for new and upgraded applications. Not recommended for use
165
- in the production environment since it relies on Ruby's `Kernel#caller` which is fairly slow.
166
-
167
- *fatkodima*
168
-
169
- * Set `provider_job_id` for Backburner jobs
170
-
171
- *Cameron Matheson*
172
-
173
- * Add `perform_all_later` to enqueue multiple jobs at once
174
-
175
- This adds the ability to bulk enqueue jobs, without running callbacks, by
176
- passing multiple jobs or an array of jobs. For example:
62
+ A common mistake with Active Job is to enqueue jobs from inside a transaction,
63
+ causing them to potentially be picked and ran by another process, before the
64
+ transaction is committed, which may result in various errors.
177
65
 
178
66
  ```ruby
179
- ActiveJob.perform_all_later(MyJob.new("hello", 42), MyJob.new("world", 0))
180
-
181
- user_jobs = User.pluck(:id).map { |id| UserJob.new(user_id: id) }
182
- ActiveJob.perform_all_later(user_jobs)
67
+ Topic.transaction do
68
+ topic = Topic.create(...)
69
+ NewTopicNotificationJob.perform_later(topic)
70
+ end
183
71
  ```
184
72
 
185
- This can greatly reduce the number of round-trips to the queue datastore.
186
- For queue adapters that do not implement the new `enqueue_all` method, we
187
- fall back to enqueuing jobs individually. The Sidekiq adapter implements
188
- `enqueue_all` with `push_bulk`.
189
-
190
- This method does not use the existing `enqueue.active_job` event, but adds a
191
- new event `enqueue_all.active_job`.
192
-
193
- *Sander Verdonschot*
194
-
195
- * Don't double log the `job` when using `ActiveRecord::QueryLog`
196
-
197
- Previously if you set `config.active_record.query_log_tags` to an array that included
198
- `:job`, the job name would get logged twice. This bug has been fixed.
199
-
200
- *Alex Ghiculescu*
201
-
202
- * Add support for Sidekiq's transaction-aware client
203
-
204
- *Jonathan del Strother*
205
-
206
- * Remove QueAdapter from Active Job.
207
-
208
- After maintaining Active Job QueAdapter by Rails and Que side
209
- to support Ruby 3 keyword arguments and options provided as top level keywords,
210
- it is quite difficult to maintain it this way.
211
-
212
- Active Job Que adapter can be included in the future version of que gem itself.
213
-
214
- *Yasuo Honda*
215
-
216
- * Fix BigDecimal (de)serialization for adapters using JSON.
73
+ Now Active Job will automatically defer the enqueuing to after the transaction is committed,
74
+ and drop the job if the transaction is rolled back.
217
75
 
218
- Previously, BigDecimal was listed as not needing a serializer. However,
219
- when used with an adapter storing the job arguments as JSON, it would get
220
- serialized as a simple String, resulting in deserialization also producing
221
- a String (instead of a BigDecimal).
222
-
223
- By using a serializer, we ensure the round trip is safe.
224
-
225
- To ensure applications using BigDecimal job arguments are not subject to
226
- race conditions during deployment (where a replica running a version of
227
- Rails without BigDecimalSerializer fails to deserialize an argument
228
- serialized with it), `ActiveJob.use_big_decimal_serializer` is disabled by
229
- default, and can be set to true in a following deployment..
230
-
231
- *Sam Bostock*
232
-
233
- * Preserve full-precision `enqueued_at` timestamps for serialized jobs,
234
- allowing more accurate reporting of how long a job spent waiting in the
235
- queue before it was performed.
236
-
237
- Retains IS08601 format compatibility.
238
-
239
- *Jeremy Daer*
240
-
241
- * Add `--parent` option to job generator to specify parent class of job.
242
-
243
- Example:
244
-
245
- `bin/rails g job process_payment --parent=payment_job` generates:
76
+ Various queue implementations can choose to disable this behavior, and users can disable it,
77
+ or force it on a per job basis:
246
78
 
247
79
  ```ruby
248
- class ProcessPaymentJob < PaymentJob
249
- # ...
80
+ class NewTopicNotificationJob < ApplicationJob
81
+ self.enqueue_after_transaction_commit = :never # or `:always` or `:default`
250
82
  end
251
83
  ```
252
84
 
253
- *Gannon McGibbon*
254
-
255
- * Add more detailed description to job generator.
256
-
257
- *Gannon McGibbon*
258
-
259
- * `perform.active_job` notification payloads now include `:db_runtime`, which
260
- is the total time (in ms) taken by database queries while performing a job.
261
- This value can be used to better understand how a job's time is spent.
262
-
263
- *Jonathan Hefner*
264
-
265
- * Update `ActiveJob::QueueAdapters::QueAdapter` to remove deprecation warning.
85
+ *Jean Boussier*, *Cristian Bica*
266
86
 
267
- Remove a deprecation warning introduced in que 1.2 to prepare for changes in
268
- que 2.0 necessary for Ruby 3 compatibility.
87
+ * Do not trigger immediate loading of `ActiveJob::Base` when loading `ActiveJob::TestHelper`.
269
88
 
270
- *Damir Zekic* and *Adis Hasovic*
89
+ *Maxime Réty*
271
90
 
272
- * Add missing `bigdecimal` require in `ActiveJob::Arguments`
91
+ * Preserve the serialized timezone when deserializing `ActiveSupport::TimeWithZone` arguments.
273
92
 
274
- Could cause `uninitialized constant ActiveJob::Arguments::BigDecimal (NameError)`
275
- when loading Active Job in isolation.
93
+ *Joshua Young*
276
94
 
277
- *Jean Boussier*
95
+ * Remove deprecated `:exponentially_longer` value for the `:wait` in `retry_on`.
278
96
 
279
- * Allow testing `discard_on/retry_on ActiveJob::DeserializationError`
97
+ *Rafael Mendonça França*
280
98
 
281
- Previously in `perform_enqueued_jobs`, `deserialize_arguments_if_needed`
282
- was called before calling `perform_now`. When a record no longer exists
283
- and is serialized using GlobalID this led to raising
284
- an `ActiveJob::DeserializationError` before reaching `perform_now` call.
285
- This behavior makes difficult testing the job `discard_on/retry_on` logic.
99
+ * Remove deprecated support to set numeric values to `scheduled_at` attribute.
286
100
 
287
- Now `deserialize_arguments_if_needed` call is postponed to when `perform_now`
288
- is called.
101
+ *Rafael Mendonça França*
289
102
 
290
- Example:
103
+ * Deprecate `Rails.application.config.active_job.use_big_decimal_serializer`.
291
104
 
292
- ```ruby
293
- class UpdateUserJob < ActiveJob::Base
294
- discard_on ActiveJob::DeserializationError
295
-
296
- def perform(user)
297
- # ...
298
- end
299
- end
105
+ *Rafael Mendonça França*
300
106
 
301
- # In the test
302
- User.destroy_all
303
- assert_nothing_raised do
304
- perform_enqueued_jobs only: UpdateUserJob
305
- end
306
- ```
107
+ * Remove deprecated primitive serializer for `BigDecimal` arguments.
307
108
 
308
- *Jacopo Beschi*
109
+ *Rafael Mendonça França*
309
110
 
310
- Please check [7-0-stable](https://github.com/rails/rails/blob/7-0-stable/activejob/CHANGELOG.md) for previous changes.
111
+ Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activejob/CHANGELOG.md) for previous changes.
data/README.md CHANGED
@@ -126,6 +126,6 @@ Bug reports for the Ruby on \Rails project can be filed here:
126
126
 
127
127
  * https://github.com/rails/rails/issues
128
128
 
129
- Feature requests should be discussed on the rails-core mailing list here:
129
+ Feature requests should be discussed on the rubyonrails-core forum here:
130
130
 
131
131
  * https://discuss.rubyonrails.org/c/rubyonrails-core
@@ -101,15 +101,6 @@ module ActiveJob
101
101
  else
102
102
  if argument.respond_to?(:permitted?) && argument.respond_to?(:to_h)
103
103
  serialize_indifferent_hash(argument.to_h)
104
- elsif BigDecimal === argument && !ActiveJob.use_big_decimal_serializer
105
- ActiveJob.deprecator.warn(<<~MSG)
106
- Primitive serialization of BigDecimal job arguments is deprecated as it may serialize via .to_s using certain queue adapters.
107
- Enable config.active_job.use_big_decimal_serializer to use BigDecimalSerializer instead, which will be mandatory in Rails 7.2.
108
-
109
- Note that if your application has multiple replicas, you should only enable this setting after successfully deploying your app to Rails 7.1 first.
110
- This will ensure that during your deployment all replicas are capable of deserializing arguments serialized with BigDecimalSerializer.
111
- MSG
112
- argument
113
104
  else
114
105
  Serializers.serialize(argument)
115
106
  end
@@ -120,8 +111,6 @@ module ActiveJob
120
111
  case argument
121
112
  when nil, true, false, String, Integer, Float
122
113
  argument
123
- when BigDecimal # BigDecimal may have been legacy serialized; Remove in 7.2
124
- argument
125
114
  when Array
126
115
  argument.map { |arg| deserialize_argument(arg) }
127
116
  when Hash
@@ -40,7 +40,7 @@ module ActiveJob # :nodoc:
40
40
  # end
41
41
  #
42
42
  # Records that are passed in are serialized/deserialized using Global
43
- # ID. More information can be found in Arguments.
43
+ # ID. More information can be found in ActiveJob::Arguments.
44
44
  #
45
45
  # To enqueue a job to be performed as soon as the queuing system is free:
46
46
  #
@@ -50,7 +50,7 @@ module ActiveJob # :nodoc:
50
50
  #
51
51
  # ProcessPhotoJob.set(wait_until: Date.tomorrow.noon).perform_later(photo)
52
52
  #
53
- # More information can be found in ActiveJob::Core::ClassMethods#set
53
+ # More information can be found in ActiveJob::Core::ClassMethods#set.
54
54
  #
55
55
  # A job can also be processed immediately without sending to the queue:
56
56
  #
@@ -15,9 +15,6 @@ module ActiveJob
15
15
  # * <tt>before_perform</tt>
16
16
  # * <tt>around_perform</tt>
17
17
  # * <tt>after_perform</tt>
18
- #
19
- # NOTE: Calling the same callback multiple times will overwrite previous callback definitions.
20
- #
21
18
  module Callbacks
22
19
  extend ActiveSupport::Concern
23
20
  include ActiveSupport::Callbacks
@@ -14,9 +14,5 @@ module ActiveJob
14
14
  def perform_later(...)
15
15
  @job_class.new(...).enqueue @options
16
16
  end
17
-
18
- def perform_all_later(multi_args)
19
- @job_class.perform_all_later(multi_args, options: @options)
20
- end
21
17
  end
22
18
  end
@@ -13,9 +13,7 @@ module ActiveJob
13
13
  attr_writer :serialized_arguments
14
14
 
15
15
  # Time when the job should be performed
16
- attr_reader :scheduled_at
17
-
18
- attr_reader :_scheduled_at_time # :nodoc:
16
+ attr_accessor :scheduled_at
19
17
 
20
18
  # Job Identifier
21
19
  attr_accessor :job_id
@@ -97,7 +95,6 @@ module ActiveJob
97
95
  @job_id = SecureRandom.uuid
98
96
  @queue_name = self.class.queue_name
99
97
  @scheduled_at = nil
100
- @_scheduled_at_time = nil
101
98
  @priority = self.class.priority
102
99
  @executions = 0
103
100
  @exception_executions = {}
@@ -117,10 +114,10 @@ module ActiveJob
117
114
  "arguments" => serialize_arguments_if_needed(arguments),
118
115
  "executions" => executions,
119
116
  "exception_executions" => exception_executions,
120
- "locale" => I18n.locale.to_s,
117
+ "locale" => locale || I18n.locale.to_s,
121
118
  "timezone" => timezone,
122
119
  "enqueued_at" => Time.now.utc.iso8601(9),
123
- "scheduled_at" => _scheduled_at_time ? _scheduled_at_time.utc.iso8601(9) : nil,
120
+ "scheduled_at" => scheduled_at ? scheduled_at.utc.iso8601(9) : nil,
124
121
  }
125
122
  end
126
123
 
@@ -174,18 +171,6 @@ module ActiveJob
174
171
  self
175
172
  end
176
173
 
177
- def scheduled_at=(value)
178
- @_scheduled_at_time = if value&.is_a?(Numeric)
179
- ActiveJob.deprecator.warn(<<~MSG.squish)
180
- Assigning a numeric/epoch value to scheduled_at is deprecated. Use a Time object instead.
181
- MSG
182
- Time.at(value)
183
- else
184
- value
185
- end
186
- @scheduled_at = value
187
- end
188
-
189
174
  private
190
175
  def serialize_arguments_if_needed(arguments)
191
176
  if arguments_serialized?
@@ -211,7 +196,7 @@ module ActiveJob
211
196
  end
212
197
 
213
198
  def arguments_serialized?
214
- defined?(@serialized_arguments) && @serialized_arguments
199
+ @serialized_arguments
215
200
  end
216
201
  end
217
202
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module EnqueueAfterTransactionCommit # :nodoc:
5
+ private
6
+ def raw_enqueue
7
+ after_transaction = case self.class.enqueue_after_transaction_commit
8
+ when :always
9
+ true
10
+ when :never
11
+ false
12
+ else # :default
13
+ queue_adapter.enqueue_after_transaction_commit?
14
+ end
15
+
16
+ if after_transaction
17
+ self.successfully_enqueued = true
18
+ ActiveRecord.after_all_transactions_commit do
19
+ self.successfully_enqueued = false
20
+ super
21
+ end
22
+ self
23
+ else
24
+ super
25
+ end
26
+ end
27
+ end
28
+ end
@@ -21,7 +21,7 @@ module ActiveJob
21
21
  adapter_jobs.each do |job|
22
22
  job.successfully_enqueued = false
23
23
  if job.scheduled_at
24
- queue_adapter.enqueue_at(job, job._scheduled_at_time.to_f)
24
+ queue_adapter.enqueue_at(job, job.scheduled_at.to_f)
25
25
  else
26
26
  queue_adapter.enqueue(job)
27
27
  end
@@ -40,6 +40,20 @@ module ActiveJob
40
40
  module Enqueuing
41
41
  extend ActiveSupport::Concern
42
42
 
43
+ included do
44
+ ##
45
+ # :singleton-method:
46
+ #
47
+ # Defines if enqueueing this job from inside an Active Record transaction
48
+ # automatically defers the enqueue to after the transaction commits.
49
+ #
50
+ # It can be set on a per job basis:
51
+ # - `:always` forces the job to be deferred.
52
+ # - `:never` forces the job to be queued immediately.
53
+ # - `:default` lets the queue adapter define the behavior (recommended).
54
+ class_attribute :enqueue_after_transaction_commit, instance_accessor: false, instance_predicate: false, default: :never
55
+ end
56
+
43
57
  # Includes the +perform_later+ method for job initialization.
44
58
  module ClassMethods
45
59
  # Push a job onto the queue. By default the arguments must be either String,
@@ -50,9 +64,21 @@ module ActiveJob
50
64
  # custom serializers.
51
65
  #
52
66
  # Returns an instance of the job class queued with arguments available in
53
- # Job#arguments or false if the enqueue did not succeed.
67
+ # Job#arguments or +false+ if the enqueue did not succeed.
54
68
  #
55
69
  # After the attempted enqueue, the job will be yielded to an optional block.
70
+ #
71
+ # If Active Job is used conjointly with Active Record, and #perform_later is called
72
+ # inside an Active Record transaction, then the enqueue is implicitly deferred to after
73
+ # the transaction is committed, or dropped if it's rolled back. In such case #perform_later
74
+ # will return the job instance like if it was successfully enqueued, but will still return
75
+ # +false+ if a callback prevented the job from being enqueued.
76
+ #
77
+ # This behavior can be changed on a per job basis:
78
+ #
79
+ # class NotificationJob < ApplicationJob
80
+ # self.enqueue_after_transaction_commit = false
81
+ # end
56
82
  def perform_later(...)
57
83
  job = job_or_instantiate(...)
58
84
  enqueue_result = job.enqueue
@@ -63,7 +89,7 @@ module ActiveJob
63
89
  end
64
90
 
65
91
  private
66
- def job_or_instantiate(*args) # :doc:
92
+ def job_or_instantiate(*args, &_) # :doc:
67
93
  args.first.is_a?(self) ? args.first : new(*args)
68
94
  end
69
95
  ruby2_keywords(:job_or_instantiate)
@@ -89,8 +115,20 @@ module ActiveJob
89
115
  self.successfully_enqueued = false
90
116
 
91
117
  run_callbacks :enqueue do
118
+ raw_enqueue
119
+ end
120
+
121
+ if successfully_enqueued?
122
+ self
123
+ else
124
+ false
125
+ end
126
+ end
127
+
128
+ private
129
+ def raw_enqueue
92
130
  if scheduled_at
93
- queue_adapter.enqueue_at self, _scheduled_at_time.to_f
131
+ queue_adapter.enqueue_at self, scheduled_at.to_f
94
132
  else
95
133
  queue_adapter.enqueue self
96
134
  end
@@ -99,12 +137,5 @@ module ActiveJob
99
137
  rescue EnqueueError => e
100
138
  self.enqueue_error = e
101
139
  end
102
-
103
- if successfully_enqueued?
104
- self
105
- else
106
- false
107
- end
108
- end
109
140
  end
110
141
  end
@@ -21,7 +21,7 @@ module ActiveJob
21
21
  # You can also pass a block that'll be invoked if the retry attempts fail for custom logic rather than letting
22
22
  # the exception bubble up. This block is yielded with the job instance as the first and the error instance as the second parameter.
23
23
  #
24
- # `retry_on` and `discard_on` handlers are searched from bottom to top, and up the class hierarchy. The handler of the first class for
24
+ # +retry_on+ and +discard_on+ handlers are searched from bottom to top, and up the class hierarchy. The handler of the first class for
25
25
  # which <tt>exception.is_a?(klass)</tt> holds true is the one invoked, if any.
26
26
  #
27
27
  # ==== Options
@@ -29,8 +29,8 @@ module ActiveJob
29
29
  # as a computing proc that takes the number of executions so far as an argument, or as a symbol reference of
30
30
  # <tt>:polynomially_longer</tt>, which applies the wait algorithm of <tt>((executions**4) + (Kernel.rand * (executions**4) * jitter)) + 2</tt>
31
31
  # (first wait ~3s, then ~18s, then ~83s, etc)
32
- # * <tt>:attempts</tt> - Re-enqueues the job the specified number of times (default: 5 attempts) or a symbol reference of <tt>:unlimited</tt>
33
- # to retry the job until it succeeds
32
+ # * <tt>:attempts</tt> - Enqueues the job the specified number of times (default: 5 attempts) or a symbol reference of <tt>:unlimited</tt>
33
+ # to retry the job until it succeeds. The number of attempts includes the original job execution.
34
34
  # * <tt>:queue</tt> - Re-enqueues the job on a different queue
35
35
  # * <tt>:priority</tt> - Re-enqueues the job with a different priority
36
36
  # * <tt>:jitter</tt> - A random delay of wait time used when calculating backoff. The default is 15% (0.15) which represents the upper bound of possible wait time (expressed as a percentage)
@@ -60,12 +60,6 @@ module ActiveJob
60
60
  # end
61
61
  # end
62
62
  def retry_on(*exceptions, wait: 3.seconds, attempts: 5, queue: nil, priority: nil, jitter: JITTER_DEFAULT)
63
- if wait == :exponentially_longer
64
- ActiveJob.deprecator.warn(<<~MSG.squish)
65
- `wait: :exponentially_longer` will actually wait polynomially longer and is therefore deprecated.
66
- Prefer `wait: :polynomially_longer` to avoid confusion and keep the same behavior.
67
- MSG
68
- end
69
63
  rescue_from(*exceptions) do |error|
70
64
  executions = executions_for(exceptions)
71
65
  if attempts == :unlimited || executions < attempts
@@ -90,7 +84,7 @@ module ActiveJob
90
84
  #
91
85
  # You can also pass a block that'll be invoked. This block is yielded with the job instance as the first and the error instance as the second parameter.
92
86
  #
93
- # `retry_on` and `discard_on` handlers are searched from bottom to top, and up the class hierarchy. The handler of the first class for
87
+ # +retry_on+ and +discard_on+ handlers are searched from bottom to top, and up the class hierarchy. The handler of the first class for
94
88
  # which <tt>exception.is_a?(klass)</tt> holds true is the one invoked, if any.
95
89
  #
96
90
  # ==== Example
@@ -156,7 +150,8 @@ module ActiveJob
156
150
  # end
157
151
  def retry_job(options = {})
158
152
  instrument :enqueue_retry, options.slice(:error, :wait) do
159
- enqueue options
153
+ job = dup
154
+ job.enqueue options
160
155
  end
161
156
  end
162
157
 
@@ -168,7 +163,7 @@ module ActiveJob
168
163
  jitter = jitter == JITTER_DEFAULT ? self.class.retry_jitter : (jitter || 0.0)
169
164
 
170
165
  case seconds_or_duration_or_algorithm
171
- when :exponentially_longer, :polynomially_longer
166
+ when :polynomially_longer
172
167
  # This delay uses a polynomial backoff strategy, which was previously misnamed as exponential
173
168
  delay = executions**4
174
169
  delay_jitter = determine_jitter_for_delay(delay, jitter)
@@ -8,9 +8,9 @@ module ActiveJob
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 7
11
- MINOR = 1
12
- TINY = 5
13
- PRE = "1"
11
+ MINOR = 2
12
+ TINY = 3
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -50,7 +50,7 @@ module ActiveJob
50
50
  info do
51
51
  jobs = event.payload[:jobs]
52
52
  adapter = event.payload[:adapter]
53
- enqueued_count = event.payload[:enqueued_count]
53
+ enqueued_count = event.payload[:enqueued_count].to_i
54
54
 
55
55
  if enqueued_count == jobs.size
56
56
  enqueued_jobs_message(adapter, jobs)
@@ -125,7 +125,7 @@ module ActiveJob
125
125
  "Stopped retrying #{job.class} (Job ID: #{job.job_id}) due to a #{ex.class} (#{ex.message}), which reoccurred on #{job.executions} attempts."
126
126
  end
127
127
  end
128
- subscribe_log_level :enqueue_retry, :error
128
+ subscribe_log_level :retry_stopped, :error
129
129
 
130
130
  def discard(event)
131
131
  job = event.payload[:job]
@@ -4,17 +4,31 @@ require "active_support/tagged_logging"
4
4
  require "active_support/logger"
5
5
 
6
6
  module ActiveJob
7
- module Logging # :nodoc:
7
+ module Logging
8
8
  extend ActiveSupport::Concern
9
9
 
10
10
  included do
11
+ ##
12
+ # Accepts a logger conforming to the interface of Log4r or the default
13
+ # Ruby +Logger+ class. You can retrieve this logger by calling +logger+ on
14
+ # either an Active Job job class or an Active Job job instance.
11
15
  cattr_accessor :logger, default: ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT))
16
+
17
+ ##
18
+ # Configures whether a job's arguments should be logged. This can be
19
+ # useful when a job's arguments may be sensitive and so should not be
20
+ # logged.
21
+ #
22
+ # The value defaults to +true+, but this can be configured with
23
+ # +config.active_job.log_arguments+. Additionally, individual jobs can
24
+ # also configure a value, which will apply to themselves and any
25
+ # subclasses.
12
26
  class_attribute :log_arguments, instance_accessor: false, default: true
13
27
 
14
28
  around_enqueue(prepend: true) { |_, block| tag_logger(&block) }
15
29
  end
16
30
 
17
- def perform_now
31
+ def perform_now # :nodoc:
18
32
  tag_logger(self.class.name, self.job_id) { super }
19
33
  end
20
34
 
@@ -15,7 +15,8 @@ module ActiveJob
15
15
  # = Active Job Queue adapter
16
16
  #
17
17
  # The +ActiveJob::QueueAdapter+ module is used to load the
18
- # correct adapter. The default queue adapter is the +:async+ queue.
18
+ # correct adapter. The default queue adapter is +:async+,
19
+ # which loads the ActiveJob::QueueAdapters::AsyncAdapter.
19
20
  module QueueAdapter # :nodoc:
20
21
  extend ActiveSupport::Concern
21
22
 
@@ -24,21 +25,21 @@ module ActiveJob
24
25
  class_attribute :_queue_adapter, instance_accessor: false, instance_predicate: false
25
26
 
26
27
  delegate :queue_adapter, to: :class
27
-
28
- self.queue_adapter = :async
29
28
  end
30
29
 
31
30
  # Includes the setter method for changing the active queue adapter.
32
31
  module ClassMethods
33
32
  # Returns the backend queue provider. The default queue adapter
34
- # is the +:async+ queue. See QueueAdapters for more information.
33
+ # is +:async+. See QueueAdapters for more information.
35
34
  def queue_adapter
35
+ self.queue_adapter = :async if _queue_adapter.nil?
36
36
  _queue_adapter
37
37
  end
38
38
 
39
39
  # Returns string denoting the name of the configured queue adapter.
40
40
  # By default returns <tt>"async"</tt>.
41
41
  def queue_adapter_name
42
+ self.queue_adapter = :async if _queue_adapter_name.nil?
42
43
  _queue_adapter_name
43
44
  end
44
45
 
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module QueueAdapters
5
+ # = Active Job Abstract Adapter
6
+ #
7
+ # Active Job supports multiple job queue systems. ActiveJob::QueueAdapters::AbstractAdapter
8
+ # forms the abstraction layer which makes this possible.
9
+ class AbstractAdapter
10
+ # Defines whether enqueuing should happen implicitly to after commit when called
11
+ # from inside a transaction. Most adapters should return true, but some adapters
12
+ # that use the same database as Active Record and are transaction aware can return
13
+ # false to continue enqueuing jobs as part of the transaction.
14
+ def enqueue_after_transaction_commit?
15
+ true
16
+ end
17
+
18
+ def enqueue(job)
19
+ raise NotImplementedError
20
+ end
21
+
22
+ def enqueue_at(job, timestamp)
23
+ raise NotImplementedError
24
+ end
25
+ end
26
+ end
27
+ end
@@ -30,7 +30,7 @@ module ActiveJob
30
30
  # The adapter uses a {Concurrent Ruby}[https://github.com/ruby-concurrency/concurrent-ruby] thread pool to schedule and execute
31
31
  # jobs. Since jobs share a single thread pool, long-running jobs will block
32
32
  # short-lived jobs. Fine for dev/test; bad for production.
33
- class AsyncAdapter
33
+ class AsyncAdapter < AbstractAdapter
34
34
  # See {Concurrent::ThreadPoolExecutor}[https://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ThreadPoolExecutor.html] for executor options.
35
35
  def initialize(**executor_options)
36
36
  @scheduler = Scheduler.new(**executor_options)
@@ -14,7 +14,7 @@ module ActiveJob
14
14
  # To use Backburner set the queue_adapter config to +:backburner+.
15
15
  #
16
16
  # Rails.application.config.active_job.queue_adapter = :backburner
17
- class BackburnerAdapter
17
+ class BackburnerAdapter < AbstractAdapter
18
18
  def enqueue(job) # :nodoc:
19
19
  response = Backburner::Worker.enqueue(JobWrapper, [job.serialize], queue: job.queue_name, pri: job.priority)
20
20
  job.provider_job_id = response[:id] if response.is_a?(Hash)
@@ -15,7 +15,15 @@ module ActiveJob
15
15
  # To use Delayed Job, set the queue_adapter config to +:delayed_job+.
16
16
  #
17
17
  # Rails.application.config.active_job.queue_adapter = :delayed_job
18
- class DelayedJobAdapter
18
+ class DelayedJobAdapter < AbstractAdapter
19
+ def initialize(enqueue_after_transaction_commit: false)
20
+ @enqueue_after_transaction_commit = enqueue_after_transaction_commit
21
+ end
22
+
23
+ def enqueue_after_transaction_commit? # :nodoc:
24
+ @enqueue_after_transaction_commit
25
+ end
26
+
19
27
  def enqueue(job) # :nodoc:
20
28
  delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, priority: job.priority)
21
29
  job.provider_job_id = delayed_job.id
@@ -10,7 +10,11 @@ module ActiveJob
10
10
  # To use the Inline set the queue_adapter config to +:inline+.
11
11
  #
12
12
  # Rails.application.config.active_job.queue_adapter = :inline
13
- class InlineAdapter
13
+ class InlineAdapter < AbstractAdapter
14
+ def enqueue_after_transaction_commit? # :nodoc:
15
+ false
16
+ end
17
+
14
18
  def enqueue(job) # :nodoc:
15
19
  Base.execute(job.serialize)
16
20
  end
@@ -18,7 +18,15 @@ module ActiveJob
18
18
  # To use queue_classic set the queue_adapter config to +:queue_classic+.
19
19
  #
20
20
  # Rails.application.config.active_job.queue_adapter = :queue_classic
21
- class QueueClassicAdapter
21
+ class QueueClassicAdapter < AbstractAdapter
22
+ def initialize(enqueue_after_transaction_commit: false)
23
+ @enqueue_after_transaction_commit = enqueue_after_transaction_commit
24
+ end
25
+
26
+ def enqueue_after_transaction_commit? # :nodoc:
27
+ @enqueue_after_transaction_commit
28
+ end
29
+
22
30
  def enqueue(job) # :nodoc:
23
31
  qc_job = build_queue(job.queue_name).enqueue("#{JobWrapper.name}.perform", job.serialize)
24
32
  job.provider_job_id = qc_job["id"] if qc_job.is_a?(Hash)
@@ -27,7 +27,7 @@ module ActiveJob
27
27
  # To use Resque set the queue_adapter config to +:resque+.
28
28
  #
29
29
  # Rails.application.config.active_job.queue_adapter = :resque
30
- class ResqueAdapter
30
+ class ResqueAdapter < AbstractAdapter
31
31
  def enqueue(job) # :nodoc:
32
32
  JobWrapper.instance_variable_set(:@queue, job.queue_name)
33
33
  Resque.enqueue_to job.queue_name, JobWrapper, job.serialize
@@ -17,7 +17,7 @@ module ActiveJob
17
17
  # To use Sidekiq set the queue_adapter config to +:sidekiq+.
18
18
  #
19
19
  # Rails.application.config.active_job.queue_adapter = :sidekiq
20
- class SidekiqAdapter
20
+ class SidekiqAdapter < AbstractAdapter
21
21
  def enqueue(job) # :nodoc:
22
22
  job.provider_job_id = JobWrapper.set(
23
23
  wrapped: job.class,
@@ -17,7 +17,7 @@ module ActiveJob
17
17
  # To use Sneakers set the queue_adapter config to +:sneakers+.
18
18
  #
19
19
  # Rails.application.config.active_job.queue_adapter = :sneakers
20
- class SneakersAdapter
20
+ class SneakersAdapter < AbstractAdapter
21
21
  def initialize
22
22
  @monitor = Monitor.new
23
23
  end
@@ -17,7 +17,7 @@ module ActiveJob
17
17
  # To use Sucker Punch set the queue_adapter config to +:sucker_punch+.
18
18
  #
19
19
  # Rails.application.config.active_job.queue_adapter = :sucker_punch
20
- class SuckerPunchAdapter
20
+ class SuckerPunchAdapter < AbstractAdapter
21
21
  def enqueue(job) # :nodoc:
22
22
  if JobWrapper.respond_to?(:perform_async)
23
23
  # sucker_punch 2.0 API
@@ -11,10 +11,18 @@ module ActiveJob
11
11
  # To use the test adapter set +queue_adapter+ config to +:test+.
12
12
  #
13
13
  # Rails.application.config.active_job.queue_adapter = :test
14
- class TestAdapter
15
- attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter, :reject, :queue, :at)
14
+ class TestAdapter < AbstractAdapter
15
+ attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter, :reject, :queue, :at, :enqueue_after_transaction_commit)
16
16
  attr_writer(:enqueued_jobs, :performed_jobs)
17
17
 
18
+ def initialize(enqueue_after_transaction_commit: true)
19
+ @enqueue_after_transaction_commit = enqueue_after_transaction_commit
20
+ end
21
+
22
+ def enqueue_after_transaction_commit? # :nodoc:
23
+ @enqueue_after_transaction_commit
24
+ end
25
+
18
26
  # Provides a store of all the enqueued jobs with the TestAdapter so you can check them.
19
27
  def enqueued_jobs
20
28
  @enqueued_jobs ||= []
@@ -114,6 +114,7 @@ module ActiveJob
114
114
  module QueueAdapters
115
115
  extend ActiveSupport::Autoload
116
116
 
117
+ autoload :AbstractAdapter
117
118
  autoload :AsyncAdapter
118
119
  autoload :InlineAdapter
119
120
  autoload :BackburnerAdapter
@@ -25,9 +25,21 @@ module ActiveJob
25
25
  end
26
26
  end
27
27
 
28
+ initializer "active_job.enqueue_after_transaction_commit" do |app|
29
+ ActiveSupport.on_load(:active_job) do
30
+ ActiveSupport.on_load(:active_record) do
31
+ ActiveJob::Base.include EnqueueAfterTransactionCommit
32
+
33
+ if app.config.active_job.key?(:enqueue_after_transaction_commit)
34
+ ActiveJob::Base.enqueue_after_transaction_commit = app.config.active_job.delete(:enqueue_after_transaction_commit)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
28
40
  initializer "active_job.set_configs" do |app|
29
41
  options = app.config.active_job
30
- options.queue_adapter ||= :async
42
+ options.queue_adapter ||= (Rails.env.test? ? :test : :async)
31
43
 
32
44
  config.after_initialize do
33
45
  options.each do |k, v|
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "singleton"
4
+
3
5
  module ActiveJob
4
6
  module Serializers
5
7
  # Base class for serializing and deserializing custom objects.
@@ -39,10 +39,13 @@ module ActiveJob
39
39
  end
40
40
 
41
41
  def before_setup # :nodoc:
42
- test_adapter = queue_adapter_for_test
43
-
42
+ queue_adapter_specific_to_this_test_class = queue_adapter_for_test
44
43
  queue_adapter_changed_jobs.each do |klass|
45
- klass.enable_test_adapter(test_adapter)
44
+ if queue_adapter_specific_to_this_test_class
45
+ klass.enable_test_adapter(queue_adapter_specific_to_this_test_class)
46
+ elsif klass._queue_adapter.nil?
47
+ klass.enable_test_adapter(ActiveJob::QueueAdapters::TestAdapter.new)
48
+ end
46
49
  end
47
50
 
48
51
  clear_enqueued_jobs
@@ -61,7 +64,6 @@ module ActiveJob
61
64
  # Override this method to specify a different adapter. The adapter must
62
65
  # implement the same interface as ActiveJob::QueueAdapters::TestAdapter.
63
66
  def queue_adapter_for_test
64
- ActiveJob::QueueAdapters::TestAdapter.new
65
67
  end
66
68
 
67
69
  # Asserts that the number of enqueued jobs matches the given number.
@@ -118,6 +120,8 @@ module ActiveJob
118
120
  # end
119
121
  # end
120
122
  def assert_enqueued_jobs(number, only: nil, except: nil, queue: nil, &block)
123
+ require_active_job_test_adapter!("assert_enqueued_jobs")
124
+
121
125
  if block_given?
122
126
  original_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
123
127
 
@@ -180,6 +184,8 @@ module ActiveJob
180
184
  #
181
185
  # assert_enqueued_jobs 0, &block
182
186
  def assert_no_enqueued_jobs(only: nil, except: nil, queue: nil, &block)
187
+ require_active_job_test_adapter!("assert_no_enqueued_jobs")
188
+
183
189
  assert_enqueued_jobs 0, only: only, except: except, queue: queue, &block
184
190
  end
185
191
 
@@ -270,6 +276,8 @@ module ActiveJob
270
276
  # end
271
277
  # end
272
278
  def assert_performed_jobs(number, only: nil, except: nil, queue: nil, &block)
279
+ require_active_job_test_adapter!("assert_performed_jobs")
280
+
273
281
  if block_given?
274
282
  original_count = performed_jobs.size
275
283
 
@@ -338,6 +346,8 @@ module ActiveJob
338
346
  #
339
347
  # assert_performed_jobs 0, &block
340
348
  def assert_no_performed_jobs(only: nil, except: nil, queue: nil, &block)
349
+ require_active_job_test_adapter!("assert_no_performed_jobs")
350
+
341
351
  assert_performed_jobs 0, only: only, except: except, queue: queue, &block
342
352
  end
343
353
 
@@ -394,6 +404,8 @@ module ActiveJob
394
404
  # end
395
405
  # end
396
406
  def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block)
407
+ require_active_job_test_adapter!("assert_enqueued_with")
408
+
397
409
  expected = { job: job, args: args, at: at, queue: queue, priority: priority }.compact
398
410
  expected_args = prepare_args_for_assertion(expected)
399
411
  potential_matches = []
@@ -496,6 +508,8 @@ module ActiveJob
496
508
  # end
497
509
  # end
498
510
  def assert_performed_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block)
511
+ require_active_job_test_adapter!("assert_performed_with")
512
+
499
513
  expected = { job: job, args: args, at: at, queue: queue, priority: priority }.compact
500
514
  expected_args = prepare_args_for_assertion(expected)
501
515
  potential_matches = []
@@ -604,7 +618,10 @@ module ActiveJob
604
618
  # If queue_adapter_for_test is overridden to return a different adapter,
605
619
  # +perform_enqueued_jobs+ will merely execute the block.
606
620
  def perform_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil, &block)
607
- return flush_enqueued_jobs(only: only, except: except, queue: queue, at: at) unless block_given?
621
+ unless block_given?
622
+ require_active_job_test_adapter!("perform_enqueued_jobs (without a block)")
623
+ return flush_enqueued_jobs(only: only, except: except, queue: queue, at: at)
624
+ end
608
625
 
609
626
  return _assert_nothing_raised_or_warn("perform_enqueued_jobs", &block) unless using_test_adapter?
610
627
 
@@ -646,6 +663,12 @@ module ActiveJob
646
663
  end
647
664
 
648
665
  private
666
+ def require_active_job_test_adapter!(method)
667
+ unless using_test_adapter?
668
+ raise ArgumentError.new("#{method} requires the Active Job test adapter, you're using #{queue_adapter.class.name}.")
669
+ end
670
+ end
671
+
649
672
  def using_test_adapter?
650
673
  queue_adapter.is_a?(ActiveJob::QueueAdapters::TestAdapter)
651
674
  end
data/lib/active_job.rb CHANGED
@@ -39,6 +39,7 @@ module ActiveJob
39
39
  autoload :Arguments
40
40
  autoload :DeserializationError, "active_job/arguments"
41
41
  autoload :SerializationError, "active_job/arguments"
42
+ autoload :EnqueueAfterTransactionCommit
42
43
 
43
44
  eager_autoload do
44
45
  autoload :Serializers
@@ -48,16 +49,20 @@ module ActiveJob
48
49
  autoload :TestCase
49
50
  autoload :TestHelper
50
51
 
51
- ##
52
- # :singleton-method:
53
- # If false, \Rails will preserve the legacy serialization of BigDecimal job arguments as Strings.
54
- # If true, \Rails will use the new BigDecimalSerializer to (de)serialize BigDecimal losslessly.
55
- # Legacy serialization will be removed in \Rails 7.2, along with this config.
56
- singleton_class.attr_accessor :use_big_decimal_serializer
57
- self.use_big_decimal_serializer = false
52
+ def self.use_big_decimal_serializer
53
+ ActiveJob.deprecator.warn <<-WARNING.squish
54
+ Rails.application.config.active_job.use_big_decimal_serializer is deprecated and will be removed in Rails 8.0.
55
+ WARNING
56
+ end
57
+
58
+ def self.use_big_decimal_serializer=(value)
59
+ ActiveJob.deprecator.warn <<-WARNING.squish
60
+ Rails.application.config.active_job.use_big_decimal_serializer is deprecated and will be removed in Rails 8.0.
61
+ WARNING
62
+ end
58
63
 
59
64
  ##
60
- # :singleton-method:
65
+ # :singleton-method: verbose_enqueue_logs
61
66
  #
62
67
  # Specifies if the methods calling background job enqueue should be logged below
63
68
  # their relevant enqueue log lines. Defaults to false.
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activejob
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.5.1
4
+ version: 7.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-12-10 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activesupport
@@ -16,14 +15,14 @@ dependencies:
16
15
  requirements:
17
16
  - - '='
18
17
  - !ruby/object:Gem::Version
19
- version: 7.1.5.1
18
+ version: 7.2.3
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - '='
25
24
  - !ruby/object:Gem::Version
26
- version: 7.1.5.1
25
+ version: 7.2.3
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: globalid
29
28
  requirement: !ruby/object:Gem::Requirement
@@ -54,6 +53,7 @@ files:
54
53
  - lib/active_job/configured_job.rb
55
54
  - lib/active_job/core.rb
56
55
  - lib/active_job/deprecator.rb
56
+ - lib/active_job/enqueue_after_transaction_commit.rb
57
57
  - lib/active_job/enqueuing.rb
58
58
  - lib/active_job/exceptions.rb
59
59
  - lib/active_job/execution.rb
@@ -63,6 +63,7 @@ files:
63
63
  - lib/active_job/logging.rb
64
64
  - lib/active_job/queue_adapter.rb
65
65
  - lib/active_job/queue_adapters.rb
66
+ - lib/active_job/queue_adapters/abstract_adapter.rb
66
67
  - lib/active_job/queue_adapters/async_adapter.rb
67
68
  - lib/active_job/queue_adapters/backburner_adapter.rb
68
69
  - lib/active_job/queue_adapters/delayed_job_adapter.rb
@@ -102,12 +103,11 @@ licenses:
102
103
  - MIT
103
104
  metadata:
104
105
  bug_tracker_uri: https://github.com/rails/rails/issues
105
- changelog_uri: https://github.com/rails/rails/blob/v7.1.5.1/activejob/CHANGELOG.md
106
- documentation_uri: https://api.rubyonrails.org/v7.1.5.1/
106
+ changelog_uri: https://github.com/rails/rails/blob/v7.2.3/activejob/CHANGELOG.md
107
+ documentation_uri: https://api.rubyonrails.org/v7.2.3/
107
108
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
108
- source_code_uri: https://github.com/rails/rails/tree/v7.1.5.1/activejob
109
+ source_code_uri: https://github.com/rails/rails/tree/v7.2.3/activejob
109
110
  rubygems_mfa_required: 'true'
110
- post_install_message:
111
111
  rdoc_options: []
112
112
  require_paths:
113
113
  - lib
@@ -115,15 +115,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
115
115
  requirements:
116
116
  - - ">="
117
117
  - !ruby/object:Gem::Version
118
- version: 2.7.0
118
+ version: 3.1.0
119
119
  required_rubygems_version: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - ">="
122
122
  - !ruby/object:Gem::Version
123
123
  version: '0'
124
124
  requirements: []
125
- rubygems_version: 3.5.22
126
- signing_key:
125
+ rubygems_version: 3.6.9
127
126
  specification_version: 4
128
127
  summary: Job framework with pluggable queues.
129
128
  test_files: []