activejob 7.0.8 → 7.2.0

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -214
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +2 -2
  5. data/lib/active_job/arguments.rb +18 -32
  6. data/lib/active_job/base.rb +1 -1
  7. data/lib/active_job/callbacks.rb +3 -8
  8. data/lib/active_job/configured_job.rb +4 -0
  9. data/lib/active_job/core.rb +11 -6
  10. data/lib/active_job/deprecator.rb +7 -0
  11. data/lib/active_job/enqueue_after_transaction_commit.rb +28 -0
  12. data/lib/active_job/enqueuing.rb +71 -12
  13. data/lib/active_job/exceptions.rb +44 -7
  14. data/lib/active_job/execution.rb +5 -2
  15. data/lib/active_job/gem_version.rb +3 -3
  16. data/lib/active_job/instrumentation.rb +18 -10
  17. data/lib/active_job/log_subscriber.rb +80 -8
  18. data/lib/active_job/logging.rb +16 -2
  19. data/lib/active_job/queue_adapter.rb +18 -6
  20. data/lib/active_job/queue_adapters/abstract_adapter.rb +27 -0
  21. data/lib/active_job/queue_adapters/async_adapter.rb +3 -3
  22. data/lib/active_job/queue_adapters/backburner_adapter.rb +8 -4
  23. data/lib/active_job/queue_adapters/delayed_job_adapter.rb +10 -2
  24. data/lib/active_job/queue_adapters/inline_adapter.rb +6 -2
  25. data/lib/active_job/queue_adapters/queue_classic_adapter.rb +13 -5
  26. data/lib/active_job/queue_adapters/resque_adapter.rb +2 -2
  27. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +43 -15
  28. data/lib/active_job/queue_adapters/sneakers_adapter.rb +2 -2
  29. data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +4 -4
  30. data/lib/active_job/queue_adapters/test_adapter.rb +13 -5
  31. data/lib/active_job/queue_adapters.rb +9 -7
  32. data/lib/active_job/queue_priority.rb +18 -1
  33. data/lib/active_job/railtie.rb +38 -7
  34. data/lib/active_job/serializers/big_decimal_serializer.rb +22 -0
  35. data/lib/active_job/serializers/duration_serializer.rb +4 -2
  36. data/lib/active_job/serializers/object_serializer.rb +2 -0
  37. data/lib/active_job/serializers/time_with_zone_serializer.rb +11 -2
  38. data/lib/active_job/serializers.rb +7 -3
  39. data/lib/active_job/test_helper.rb +60 -19
  40. data/lib/active_job/version.rb +1 -1
  41. data/lib/active_job.rb +34 -4
  42. data/lib/rails/generators/job/USAGE +19 -0
  43. data/lib/rails/generators/job/job_generator.rb +6 -2
  44. data/lib/rails/generators/job/templates/job.rb.tt +1 -1
  45. metadata +14 -10
  46. data/lib/active_job/queue_adapters/que_adapter.rb +0 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 235128c7d980f87db5c8868459c333bd46426236218aae248293461011c39f82
4
- data.tar.gz: d8c90ea58afcb522bb34846a4356dbc4f06063d3edd89b1486bce21d07b0272f
3
+ metadata.gz: 61775543f203855f8c8bdec31ddaa7d3c1413aab36a2de5665a726b7f5998307
4
+ data.tar.gz: 39b14d506be28b9c980fc69ac8910c8e31245aa8e19caa4a15b3511f9d90cac8
5
5
  SHA512:
6
- metadata.gz: de04d283bcec657df1b29faa766d084c95820ef6f0505633484a8e15e6421a8e1313cb2727a9dfc6b09c280f1e4a1533a0673ceb0489ac674834ec0fbbd65bf2
7
- data.tar.gz: 3c9bb2aa0e47b7482a3ec51e25747c0952f457f6770ddbbeaa56b7c6bac137a2046a8df778237fb4a2500b533962711b1d5e0b5efceaff49bb3d2cf725fc4f0b
6
+ metadata.gz: 6351b9fb7e90d452428f30db98315ff523cbd781f409df3fba0ae7241fdedc0ae52514a3d5c4acd01b9474e235844e683a832f6631d65e8ea77b261bea0b3cf9
7
+ data.tar.gz: 9e18505077f83dd8924cb866138d0809b83fb9df68623f9a5e67cc0dbe1fcdcaea4a59c9de5cd9a4884684a1202b54a8ad0da657f08f5474a6790d20436be130
data/CHANGELOG.md CHANGED
@@ -1,246 +1,67 @@
1
- ## Rails 7.0.8 (September 09, 2023) ##
1
+ ## Rails 7.2.0 (August 09, 2024) ##
2
2
 
3
- * Fix Active Job log message to correctly report a job failed to enqueue
4
- when the adapter raises an `ActiveJob::EnqueueError`.
3
+ * All tests now respect the `active_job.queue_adapter` config.
5
4
 
6
- *Ben Sheldon*
5
+ Previously if you had set `config.active_job.queue_adapter` in your `config/application.rb`
6
+ or `config/environments/test.rb` file, the adapter you selected was previously not used consistently
7
+ across all tests. In some tests your adapter would be used, but other tests would use the `TestAdapter`.
7
8
 
9
+ In Rails 7.2, all tests will respect the `queue_adapter` config if provided. If no config is provided,
10
+ the `TestAdapter` will continue to be used.
8
11
 
9
- ## Rails 7.0.7.2 (August 22, 2023) ##
10
-
11
- * No changes.
12
-
13
-
14
- ## Rails 7.0.7.1 (August 22, 2023) ##
15
-
16
- * No changes.
17
-
18
-
19
- ## Rails 7.0.7 (August 09, 2023) ##
20
-
21
- * No changes.
22
-
23
-
24
- ## Rails 7.0.6 (June 29, 2023) ##
25
-
26
- * Fix error Active Job passed class with `permitted?`.
27
-
28
- *Alex Baldwin*
29
-
30
-
31
- ## Rails 7.0.5.1 (June 26, 2023) ##
32
-
33
- * No changes.
34
-
35
-
36
- ## Rails 7.0.5 (May 24, 2023) ##
37
-
38
- * Make delayed job `display_name` failsafe.
39
-
40
- *codez*
41
-
42
- * Don't double log the `job` when using `ActiveRecord::QueryLog`
43
-
44
- Previously if you set `config.active_record.query_log_tags` to an array that included
45
- `:job`, the job name would get logged twice. This bug has been fixed.
12
+ See [#48585](https://github.com/rails/rails/pull/48585) for more details.
46
13
 
47
14
  *Alex Ghiculescu*
48
15
 
16
+ * Make Active Job transaction aware when used conjointly with Active Record.
49
17
 
50
- ## Rails 7.0.4.3 (March 13, 2023) ##
51
-
52
- * No changes.
53
-
54
-
55
- ## Rails 7.0.4.2 (January 24, 2023) ##
56
-
57
- * No changes.
58
-
59
-
60
- ## Rails 7.0.4.1 (January 17, 2023) ##
61
-
62
- * No changes.
63
-
64
-
65
- ## Rails 7.0.4 (September 09, 2022) ##
66
-
67
- * Update `ActiveJob::QueueAdapters::QueAdapter` to remove deprecation warning.
68
-
69
- Remove a deprecation warning introduced in que 1.2 to prepare for changes in
70
- que 2.0 necessary for Ruby 3 compatibility.
71
-
72
- *Damir Zekic* and *Adis Hasovic*
73
-
74
- ## Rails 7.0.3.1 (July 12, 2022) ##
75
-
76
- * No changes.
77
-
78
-
79
- ## Rails 7.0.3 (May 09, 2022) ##
80
-
81
- * Add missing `bigdecimal` require in `ActiveJob::Arguments`
82
-
83
- Could cause `uninitialized constant ActiveJob::Arguments::BigDecimal (NameError)`
84
- when loading Active Job in isolation.
85
-
86
- *Jean Boussier*
87
-
88
- ## Rails 7.0.2.4 (April 26, 2022) ##
89
-
90
- * No changes.
91
-
92
-
93
- ## Rails 7.0.2.3 (March 08, 2022) ##
94
-
95
- * No changes.
96
-
97
-
98
- ## Rails 7.0.2.2 (February 11, 2022) ##
99
-
100
- * No changes.
101
-
102
-
103
- ## Rails 7.0.2.1 (February 11, 2022) ##
104
-
105
- * No changes.
106
-
107
-
108
- ## Rails 7.0.2 (February 08, 2022) ##
109
-
110
- * No changes.
111
-
112
-
113
- ## Rails 7.0.1 (January 06, 2022) ##
114
-
115
- * Allow testing `discard_on/retry_on ActiveJob::DeserializationError`
116
-
117
- Previously in `perform_enqueued_jobs`, `deserialize_arguments_if_needed`
118
- was called before calling `perform_now`. When a record no longer exists
119
- and is serialized using GlobalID this led to raising
120
- an `ActiveJob::DeserializationError` before reaching `perform_now` call.
121
- This behaviour makes difficult testing the job `discard_on/retry_on` logic.
122
-
123
- Now `deserialize_arguments_if_needed` call is postponed to when `perform_now`
124
- is called.
125
-
126
- Example:
18
+ A common mistake with Active Job is to enqueue jobs from inside a transaction,
19
+ causing them to potentially be picked and ran by another process, before the
20
+ transaction is committed, which may result in various errors.
127
21
 
128
22
  ```ruby
129
- class UpdateUserJob < ActiveJob::Base
130
- discard_on ActiveJob::DeserializationError
131
-
132
- def perform(user)
133
- # ...
134
- end
135
- end
136
-
137
- # In the test
138
- User.destroy_all
139
- assert_nothing_raised do
140
- perform_enqueued_jobs only: UpdateUserJob
23
+ Topic.transaction do
24
+ topic = Topic.create(...)
25
+ NewTopicNotificationJob.perform_later(topic)
141
26
  end
142
27
  ```
143
28
 
144
- *Jacopo Beschi*
145
-
146
-
147
- ## Rails 7.0.0 (December 15, 2021) ##
148
-
149
- * No changes.
29
+ Now Active Job will automatically defer the enqueuing to after the transaction is committed,
30
+ and drop the job if the transaction is rolled back.
150
31
 
32
+ Various queue implementations can choose to disable this behavior, and users can disable it,
33
+ or force it on a per job basis:
151
34
 
152
- ## Rails 7.0.0.rc3 (December 14, 2021) ##
35
+ ```ruby
36
+ class NewTopicNotificationJob < ApplicationJob
37
+ self.enqueue_after_transaction_commit = :never # or `:always` or `:default`
38
+ end
39
+ ```
153
40
 
154
- * No changes.
41
+ *Jean Boussier*, *Cristian Bica*
155
42
 
43
+ * Do not trigger immediate loading of `ActiveJob::Base` when loading `ActiveJob::TestHelper`.
156
44
 
157
- ## Rails 7.0.0.rc2 (December 14, 2021) ##
45
+ *Maxime Réty*
158
46
 
159
- * No changes.
47
+ * Preserve the serialized timezone when deserializing `ActiveSupport::TimeWithZone` arguments.
160
48
 
161
- ## Rails 7.0.0.rc1 (December 06, 2021) ##
49
+ *Joshua Young*
162
50
 
163
- * Remove deprecated `:return_false_on_aborted_enqueue` option.
51
+ * Remove deprecated `:exponentially_longer` value for the `:wait` in `retry_on`.
164
52
 
165
53
  *Rafael Mendonça França*
166
54
 
167
- * Deprecated `Rails.config.active_job.skip_after_callbacks_if_terminated`.
55
+ * Remove deprecated support to set numeric values to `scheduled_at` attribute.
168
56
 
169
57
  *Rafael Mendonça França*
170
58
 
171
- * Removed deprecated behavior that was not halting `after_enqueue`/`after_perform` callbacks when a
172
- previous callback was halted with `throw :abort`.
59
+ * Deprecate `Rails.application.config.active_job.use_big_decimal_serialize`.
173
60
 
174
61
  *Rafael Mendonça França*
175
62
 
176
- * Raise an `SerializationError` in `Serializer::ModuleSerializer`
177
- if the module name is not present.
178
-
179
- *Veerpal Brar*
180
-
181
-
182
- ## Rails 7.0.0.alpha2 (September 15, 2021) ##
183
-
184
- * No changes.
185
-
186
-
187
- ## Rails 7.0.0.alpha1 (September 15, 2021) ##
188
-
189
- * Allow a job to retry indefinitely
190
-
191
- The `attempts` parameter of the `retry_on` method now accepts the
192
- symbol reference `:unlimited` in addition to a specific number of retry
193
- attempts to allow a developer to specify that a job should retry
194
- forever until it succeeds.
195
-
196
- class MyJob < ActiveJob::Base
197
- retry_on(AlwaysRetryException, attempts: :unlimited)
198
-
199
- # the actual job code
200
- end
201
-
202
- *Daniel Morton*
203
-
204
- * Added possibility to check on `:priority` in test helper methods
205
- `assert_enqueued_with` and `assert_performed_with`.
206
-
207
- *Wojciech Wnętrzak*
208
-
209
- * OpenSSL constants are now used for Digest computations.
210
-
211
- *Dirkjan Bussink*
212
-
213
- * Add a Serializer for the Range class.
214
-
215
- This should allow things like `MyJob.perform_later(range: 1..100)`.
216
-
217
- * Communicate enqueue failures to callers of `perform_later`.
218
-
219
- `perform_later` can now optionally take a block which will execute after
220
- the adapter attempts to enqueue the job. The block will receive the job
221
- instance as an argument even if the enqueue was not successful.
222
- Additionally, `ActiveJob` adapters now have the ability to raise an
223
- `ActiveJob::EnqueueError` which will be caught and stored in the job
224
- instance so code attempting to enqueue jobs can inspect any raised
225
- `EnqueueError` using the block.
226
-
227
- MyJob.perform_later do |job|
228
- unless job.successfully_enqueued?
229
- if job.enqueue_error&.message == "Redis was unavailable"
230
- # invoke some code that will retry the job after a delay
231
- end
232
- end
233
- end
234
-
235
- *Daniel Morton*
236
-
237
- * Don't log rescuable exceptions defined with `rescue_from`.
238
-
239
- *Hu Hailin*
240
-
241
- * Allow `rescue_from` to rescue all exceptions.
242
-
243
- *Adrianna Chang*, *Étienne Barrié*
63
+ * Remove deprecated primitive serializer for `BigDecimal` arguments.
244
64
 
65
+ *Rafael Mendonça França*
245
66
 
246
- Please check [6-1-stable](https://github.com/rails/rails/blob/6-1-stable/activejob/CHANGELOG.md) for previous changes.
67
+ Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activejob/CHANGELOG.md) for previous changes.
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014-2022 David Heinemeier Hansson
1
+ Copyright (c) David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -10,14 +10,14 @@ that makes it easy to turn any mailing into a job for running later. That's
10
10
  one of the most common jobs in a modern web application: sending emails outside
11
11
  the request-response cycle, so the user doesn't have to wait on it.
12
12
 
13
- The main point is to ensure that all Rails apps will have a job infrastructure
13
+ The main point is to ensure that all \Rails apps will have a job infrastructure
14
14
  in place, even if it's in the form of an "immediate runner". We can then have
15
15
  framework features and other gems build on top of that, without having to worry
16
16
  about API differences between Delayed Job and Resque. Picking your queuing
17
17
  backend becomes more of an operational concern, then. And you'll be able to
18
18
  switch between them without having to rewrite your jobs.
19
19
 
20
- You can read more about Active Job in the [Active Job Basics](https://edgeguides.rubyonrails.org/active_job_basics.html) guide.
20
+ You can read more about Active Job in the [Active Job Basics](https://guides.rubyonrails.org/active_job_basics.html) guide.
21
21
 
22
22
  ## Usage
23
23
 
@@ -46,8 +46,6 @@ module ActiveJob
46
46
  end
47
47
 
48
48
  private
49
- # :nodoc:
50
- PERMITTED_TYPES = [ NilClass, String, Integer, Float, BigDecimal, TrueClass, FalseClass ]
51
49
  # :nodoc:
52
50
  GLOBALID_KEY = "_aj_globalid"
53
51
  # :nodoc:
@@ -67,35 +65,23 @@ module ActiveJob
67
65
  OBJECT_SERIALIZER_KEY, OBJECT_SERIALIZER_KEY.to_sym,
68
66
  WITH_INDIFFERENT_ACCESS_KEY, WITH_INDIFFERENT_ACCESS_KEY.to_sym,
69
67
  ]
70
- private_constant :PERMITTED_TYPES, :RESERVED_KEYS, :GLOBALID_KEY,
68
+ private_constant :RESERVED_KEYS, :GLOBALID_KEY,
71
69
  :SYMBOL_KEYS_KEY, :RUBY2_KEYWORDS_KEY, :WITH_INDIFFERENT_ACCESS_KEY
72
70
 
73
- unless Hash.respond_to?(:ruby2_keywords_hash?) && Hash.respond_to?(:ruby2_keywords_hash)
74
- using Module.new {
75
- refine Hash do
76
- class << Hash
77
- def ruby2_keywords_hash?(hash)
78
- !new(*[hash]).default.equal?(hash)
79
- end
80
-
81
- def ruby2_keywords_hash(hash)
82
- _ruby2_keywords_hash(**hash)
83
- end
84
-
85
- private
86
- def _ruby2_keywords_hash(*args)
87
- args.last
88
- end
89
- ruby2_keywords(:_ruby2_keywords_hash)
90
- end
91
- end
92
- }
93
- end
94
-
95
71
  def serialize_argument(argument)
96
72
  case argument
97
- when *PERMITTED_TYPES
73
+ when nil, true, false, Integer, Float # Types that can hardly be subclassed
98
74
  argument
75
+ when String
76
+ if argument.class == String
77
+ argument
78
+ else
79
+ begin
80
+ Serializers.serialize(argument)
81
+ rescue SerializationError
82
+ argument
83
+ end
84
+ end
99
85
  when GlobalID::Identification
100
86
  convert_to_global_id_hash(argument)
101
87
  when Array
@@ -112,18 +98,18 @@ module ActiveJob
112
98
  result = serialize_hash(argument)
113
99
  result[aj_hash_key] = symbol_keys
114
100
  result
115
- when -> (arg) { arg.respond_to?(:permitted?) && arg.respond_to?(:to_h) }
116
- serialize_indifferent_hash(argument.to_h)
117
101
  else
118
- Serializers.serialize(argument)
102
+ if argument.respond_to?(:permitted?) && argument.respond_to?(:to_h)
103
+ serialize_indifferent_hash(argument.to_h)
104
+ else
105
+ Serializers.serialize(argument)
106
+ end
119
107
  end
120
108
  end
121
109
 
122
110
  def deserialize_argument(argument)
123
111
  case argument
124
- when String
125
- argument
126
- when *PERMITTED_TYPES
112
+ when nil, true, false, String, Integer, Float
127
113
  argument
128
114
  when Array
129
115
  argument.map { |arg| deserialize_argument(arg) }
@@ -15,7 +15,7 @@ require "active_job/timezones"
15
15
  require "active_job/translation"
16
16
 
17
17
  module ActiveJob # :nodoc:
18
- # = Active Job
18
+ # = Active Job \Base
19
19
  #
20
20
  # Active Job objects can be configured to work with different backend
21
21
  # queuing frameworks. To specify a queue adapter to use:
@@ -4,7 +4,7 @@ require "active_support/callbacks"
4
4
  require "active_support/core_ext/module/attribute_accessors"
5
5
 
6
6
  module ActiveJob
7
- # = Active Job Callbacks
7
+ # = Active Job \Callbacks
8
8
  #
9
9
  # Active Job provides hooks during the life cycle of a job. Callbacks allow you
10
10
  # to trigger logic during this cycle. Available callbacks are:
@@ -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
@@ -28,9 +25,6 @@ module ActiveJob
28
25
  end
29
26
 
30
27
  included do
31
- cattr_accessor :skip_after_callbacks_if_terminated, instance_accessor: false, default: false
32
- singleton_class.deprecate :skip_after_callbacks_if_terminated, :skip_after_callbacks_if_terminated=
33
-
34
28
  define_callbacks :perform, skip_after_callbacks_if_terminated: true
35
29
  define_callbacks :enqueue, skip_after_callbacks_if_terminated: true
36
30
  end
@@ -135,7 +129,8 @@ module ActiveJob
135
129
  # queue_as :default
136
130
  #
137
131
  # after_enqueue do |job|
138
- # $statsd.increment "enqueue-video-job.success"
132
+ # result = job.successfully_enqueued? ? "success" : "failure"
133
+ # $statsd.increment "enqueue-video-job.#{result}"
139
134
  # end
140
135
  #
141
136
  # def perform(video_id)
@@ -14,5 +14,9 @@ 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
17
21
  end
18
22
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveJob
4
+ # = Active Job \Core
5
+ #
4
6
  # Provides general behavior that will be included into every Active Job
5
7
  # object that inherits from ActiveJob::Base.
6
8
  module Core
@@ -10,7 +12,7 @@ module ActiveJob
10
12
  attr_accessor :arguments
11
13
  attr_writer :serialized_arguments
12
14
 
13
- # Timestamp when the job should be performed
15
+ # Time when the job should be performed
14
16
  attr_accessor :scheduled_at
15
17
 
16
18
  # Job Identifier
@@ -92,6 +94,7 @@ module ActiveJob
92
94
  @arguments = arguments
93
95
  @job_id = SecureRandom.uuid
94
96
  @queue_name = self.class.queue_name
97
+ @scheduled_at = nil
95
98
  @priority = self.class.priority
96
99
  @executions = 0
97
100
  @exception_executions = {}
@@ -113,7 +116,8 @@ module ActiveJob
113
116
  "exception_executions" => exception_executions,
114
117
  "locale" => I18n.locale.to_s,
115
118
  "timezone" => timezone,
116
- "enqueued_at" => Time.now.utc.iso8601
119
+ "enqueued_at" => Time.now.utc.iso8601(9),
120
+ "scheduled_at" => scheduled_at ? scheduled_at.utc.iso8601(9) : nil,
117
121
  }
118
122
  end
119
123
 
@@ -153,13 +157,14 @@ module ActiveJob
153
157
  self.exception_executions = job_data["exception_executions"]
154
158
  self.locale = job_data["locale"] || I18n.locale.to_s
155
159
  self.timezone = job_data["timezone"] || Time.zone&.name
156
- self.enqueued_at = job_data["enqueued_at"]
160
+ self.enqueued_at = Time.iso8601(job_data["enqueued_at"]) if job_data["enqueued_at"]
161
+ self.scheduled_at = Time.iso8601(job_data["scheduled_at"]) if job_data["scheduled_at"]
157
162
  end
158
163
 
159
164
  # Configures the job with the given options.
160
165
  def set(options = {}) # :nodoc:
161
- self.scheduled_at = options[:wait].seconds.from_now.to_f if options[:wait]
162
- self.scheduled_at = options[:wait_until].to_f if options[:wait_until]
166
+ self.scheduled_at = options[:wait].seconds.from_now if options[:wait]
167
+ self.scheduled_at = options[:wait_until] if options[:wait_until]
163
168
  self.queue_name = self.class.queue_name_from_part(options[:queue]) if options[:queue]
164
169
  self.priority = options[:priority].to_i if options[:priority]
165
170
 
@@ -191,7 +196,7 @@ module ActiveJob
191
196
  end
192
197
 
193
198
  def arguments_serialized?
194
- defined?(@serialized_arguments) && @serialized_arguments
199
+ @serialized_arguments
195
200
  end
196
201
  end
197
202
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ def self.deprecator # :nodoc:
5
+ @deprecator ||= ActiveSupport::Deprecation.new
6
+ end
7
+ 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
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_job/arguments"
4
-
5
3
  module ActiveJob
6
4
  # Provides behavior for enqueuing jobs.
7
5
 
@@ -9,9 +7,53 @@ module ActiveJob
9
7
  # why the adapter was unexpectedly unable to enqueue a job.
10
8
  class EnqueueError < StandardError; end
11
9
 
10
+ class << self
11
+ # Push many jobs onto the queue at once without running enqueue callbacks.
12
+ # Queue adapters may communicate the enqueue status of each job by setting
13
+ # successfully_enqueued and/or enqueue_error on the passed-in job instances.
14
+ def perform_all_later(*jobs)
15
+ jobs.flatten!
16
+ jobs.group_by(&:queue_adapter).each do |queue_adapter, adapter_jobs|
17
+ instrument_enqueue_all(queue_adapter, adapter_jobs) do
18
+ if queue_adapter.respond_to?(:enqueue_all)
19
+ queue_adapter.enqueue_all(adapter_jobs)
20
+ else
21
+ adapter_jobs.each do |job|
22
+ job.successfully_enqueued = false
23
+ if job.scheduled_at
24
+ queue_adapter.enqueue_at(job, job.scheduled_at.to_f)
25
+ else
26
+ queue_adapter.enqueue(job)
27
+ end
28
+ job.successfully_enqueued = true
29
+ rescue EnqueueError => e
30
+ job.enqueue_error = e
31
+ end
32
+ adapter_jobs.count(&:successfully_enqueued?)
33
+ end
34
+ end
35
+ end
36
+ nil
37
+ end
38
+ end
39
+
12
40
  module Enqueuing
13
41
  extend ActiveSupport::Concern
14
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
+
15
57
  # Includes the +perform_later+ method for job initialization.
16
58
  module ClassMethods
17
59
  # Push a job onto the queue. By default the arguments must be either String,
@@ -22,9 +64,21 @@ module ActiveJob
22
64
  # custom serializers.
23
65
  #
24
66
  # Returns an instance of the job class queued with arguments available in
25
- # Job#arguments or false if the enqueue did not succeed.
67
+ # Job#arguments or +false+ if the enqueue did not succeed.
26
68
  #
27
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
28
82
  def perform_later(...)
29
83
  job = job_or_instantiate(...)
30
84
  enqueue_result = job.enqueue
@@ -35,7 +89,7 @@ module ActiveJob
35
89
  end
36
90
 
37
91
  private
38
- def job_or_instantiate(*args) # :doc:
92
+ def job_or_instantiate(*args, &_) # :doc:
39
93
  args.first.is_a?(self) ? args.first : new(*args)
40
94
  end
41
95
  ruby2_keywords(:job_or_instantiate)
@@ -61,8 +115,20 @@ module ActiveJob
61
115
  self.successfully_enqueued = false
62
116
 
63
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
64
130
  if scheduled_at
65
- queue_adapter.enqueue_at self, scheduled_at
131
+ queue_adapter.enqueue_at self, scheduled_at.to_f
66
132
  else
67
133
  queue_adapter.enqueue self
68
134
  end
@@ -71,12 +137,5 @@ module ActiveJob
71
137
  rescue EnqueueError => e
72
138
  self.enqueue_error = e
73
139
  end
74
-
75
- if successfully_enqueued?
76
- self
77
- else
78
- false
79
- end
80
- end
81
140
  end
82
141
  end