activejob 5.2.7.1 → 6.1.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +109 -58
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +18 -13
  5. data/lib/active_job/arguments.rb +80 -30
  6. data/lib/active_job/base.rb +6 -1
  7. data/lib/active_job/callbacks.rb +46 -3
  8. data/lib/active_job/configured_job.rb +2 -0
  9. data/lib/active_job/core.rb +40 -21
  10. data/lib/active_job/enqueuing.rb +20 -7
  11. data/lib/active_job/exceptions.rb +60 -28
  12. data/lib/active_job/execution.rb +11 -2
  13. data/lib/active_job/gem_version.rb +4 -4
  14. data/lib/active_job/instrumentation.rb +40 -0
  15. data/lib/active_job/log_subscriber.rb +140 -0
  16. data/lib/active_job/logging.rb +3 -101
  17. data/lib/active_job/queue_adapter.rb +5 -0
  18. data/lib/active_job/queue_adapters/async_adapter.rb +1 -1
  19. data/lib/active_job/queue_adapters/backburner_adapter.rb +2 -2
  20. data/lib/active_job/queue_adapters/inline_adapter.rb +1 -1
  21. data/lib/active_job/queue_adapters/que_adapter.rb +2 -2
  22. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +2 -2
  23. data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +1 -1
  24. data/lib/active_job/queue_adapters/test_adapter.rb +32 -14
  25. data/lib/active_job/queue_adapters.rb +13 -11
  26. data/lib/active_job/queue_name.rb +23 -3
  27. data/lib/active_job/railtie.rb +20 -1
  28. data/lib/active_job/serializers/date_serializer.rb +20 -0
  29. data/lib/active_job/serializers/date_time_serializer.rb +16 -0
  30. data/lib/active_job/serializers/duration_serializer.rb +23 -0
  31. data/lib/active_job/serializers/module_serializer.rb +20 -0
  32. data/lib/active_job/serializers/object_serializer.rb +53 -0
  33. data/lib/active_job/serializers/symbol_serializer.rb +20 -0
  34. data/lib/active_job/serializers/time_object_serializer.rb +13 -0
  35. data/lib/active_job/serializers/time_serializer.rb +16 -0
  36. data/lib/active_job/serializers/time_with_zone_serializer.rb +16 -0
  37. data/lib/active_job/serializers.rb +66 -0
  38. data/lib/active_job/test_helper.rb +317 -68
  39. data/lib/active_job/timezones.rb +13 -0
  40. data/lib/active_job/translation.rb +1 -1
  41. data/lib/active_job.rb +2 -1
  42. data/lib/rails/generators/job/job_generator.rb +4 -0
  43. metadata +26 -11
  44. data/lib/active_job/queue_adapters/qu_adapter.rb +0 -46
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83861bba53b1e045a1da3fd483c3bf651d54f45196c13d3206a5f7326f22090d
4
- data.tar.gz: cd70b34c0cfff67e3b463b6d0ec755a9cb75fe1cc4014ed9eabf64d764748c27
3
+ metadata.gz: 8ccbcc24e96faf85fc01b6f895b065fdad12e6801431ce6f8cbaa9643413a795
4
+ data.tar.gz: '0379200b04374460e8068915ad61d08a1ae978bc6475f6826073a377d264d62d'
5
5
  SHA512:
6
- metadata.gz: c970a47af59659f105e793110287c68025359a46fd09a6aee21f98eca637c045b7eae49ad60425664a5c7705175accd623873a46f187376334c207f6d23700ba
7
- data.tar.gz: b5a55002d089281c7a13df425d7a852c00bc16a3ff1723e342b69a8e6d4b0d1c48cbb02515740f05430f2c9cbec05af677dcc62001abd781d5450f38aa840bdd
6
+ metadata.gz: a0c2dae1d664294f6e9657d6430798fbfc3a329f649fb92b7c2effd53fd0097aec9d1b536e475970f6691ebd373c5faeacbcadc91b771177ccbe290d8cedc753
7
+ data.tar.gz: 60026f9d7a1141a7981fffd8ae99f834531073ca149ba2f62df7fb0341524544b3d196b253e85dc6e738a9fffec410fbbe99825abd667a5a062ba21fe296eec8
data/CHANGELOG.md CHANGED
@@ -1,150 +1,201 @@
1
- ## Rails 5.2.7.1 (April 26, 2022) ##
1
+ ## Rails 6.1.4.6 (February 11, 2022) ##
2
2
 
3
3
  * No changes.
4
4
 
5
5
 
6
- ## Rails 5.2.7 (March 10, 2022) ##
6
+ ## Rails 6.1.4.5 (February 11, 2022) ##
7
7
 
8
8
  * No changes.
9
9
 
10
10
 
11
- ## Rails 5.2.6.3 (March 08, 2022) ##
11
+ ## Rails 6.1.4.4 (December 15, 2021) ##
12
12
 
13
13
  * No changes.
14
14
 
15
15
 
16
- ## Rails 5.2.6.2 (February 11, 2022) ##
16
+ ## Rails 6.1.4.3 (December 14, 2021) ##
17
17
 
18
18
  * No changes.
19
19
 
20
20
 
21
- ## Rails 5.2.6.1 (February 11, 2022) ##
21
+ ## Rails 6.1.4.2 (December 14, 2021) ##
22
22
 
23
23
  * No changes.
24
24
 
25
25
 
26
- ## Rails 5.2.6 (May 05, 2021) ##
26
+ ## Rails 6.1.4.1 (August 19, 2021) ##
27
27
 
28
28
  * No changes.
29
29
 
30
30
 
31
- ## Rails 5.2.5 (March 26, 2021) ##
31
+ ## Rails 6.1.4 (June 24, 2021) ##
32
32
 
33
33
  * No changes.
34
34
 
35
35
 
36
- ## Rails 5.2.4.6 (May 05, 2021) ##
36
+ ## Rails 6.1.3.2 (May 05, 2021) ##
37
37
 
38
38
  * No changes.
39
39
 
40
40
 
41
- ## Rails 5.2.4.5 (February 10, 2021) ##
41
+ ## Rails 6.1.3.1 (March 26, 2021) ##
42
42
 
43
43
  * No changes.
44
44
 
45
45
 
46
- ## Rails 5.2.4.4 (September 09, 2020) ##
46
+ ## Rails 6.1.3 (February 17, 2021) ##
47
47
 
48
48
  * No changes.
49
49
 
50
50
 
51
- ## Rails 5.2.4.3 (May 18, 2020) ##
51
+ ## Rails 6.1.2.1 (February 10, 2021) ##
52
52
 
53
53
  * No changes.
54
54
 
55
55
 
56
- ## Rails 5.2.4.2 (March 19, 2020) ##
56
+ ## Rails 6.1.2 (February 09, 2021) ##
57
57
 
58
58
  * No changes.
59
59
 
60
60
 
61
- ## Rails 5.2.4.1 (December 18, 2019) ##
61
+ ## Rails 6.1.1 (January 07, 2021) ##
62
62
 
63
- * No changes.
63
+ * Make `retry_job` return the job that was created.
64
64
 
65
+ *Rafael Mendonça França*
65
66
 
66
- ## Rails 5.2.4 (November 27, 2019) ##
67
+ * Include `ActiveSupport::Testing::Assertions` in `ActiveJob::TestHelpers`.
67
68
 
68
- * No changes.
69
+ *Mikkel Malmberg*
69
70
 
70
71
 
71
- ## Rails 5.2.3 (March 27, 2019) ##
72
+ ## Rails 6.1.0 (December 09, 2020) ##
72
73
 
73
- * No changes.
74
+ * Recover nano precision when serializing `Time`, `TimeWithZone` and `DateTime` objects.
74
75
 
76
+ *Alan Tan*
75
77
 
76
- ## Rails 5.2.2.1 (March 11, 2019) ##
78
+ * Deprecate `config.active_job.return_false_on_aborted_enqueue`.
77
79
 
78
- * No changes.
80
+ *Rafael Mendonça França*
81
+
82
+ * Return `false` when enqueuing a job is aborted.
83
+
84
+ *Rafael Mendonça França*
85
+
86
+ * While using `perform_enqueued_jobs` test helper enqueued jobs must be stored for the later check with
87
+ `assert_enqueued_with`.
88
+
89
+ *Dmitry Polushkin*
90
+
91
+ * `ActiveJob::TestCase#perform_enqueued_jobs` without a block removes performed jobs from the queue.
92
+
93
+ That way the helper can be called multiple times and not perform a job invocation multiple times.
79
94
 
95
+ ```ruby
96
+ def test_jobs
97
+ HelloJob.perform_later("rafael")
98
+ perform_enqueued_jobs # only runs with "rafael"
99
+ HelloJob.perform_later("david")
100
+ perform_enqueued_jobs # only runs with "david"
101
+ end
102
+ ```
80
103
 
81
- ## Rails 5.2.2 (December 04, 2018) ##
104
+ *Étienne Barrié*
82
105
 
83
- * Make sure `assert_enqueued_with()` & `assert_performed_with()` work reliably with hash arguments.
106
+ * `ActiveJob::TestCase#perform_enqueued_jobs` will no longer perform retries:
84
107
 
85
- *Sharang Dashputre*
108
+ When calling `perform_enqueued_jobs` without a block, the adapter will
109
+ now perform jobs that are **already** in the queue. Jobs that will end up in
110
+ the queue afterwards won't be performed.
86
111
 
87
- * Restore `ActionController::Parameters` support to `ActiveJob::Arguments.serialize`.
112
+ This change only affects `perform_enqueued_jobs` when no block is given.
88
113
 
89
- *Bernie Chiu*
114
+ *Edouard Chin*
90
115
 
91
- * Restore `HashWithIndifferentAccess` support to `ActiveJob::Arguments.deserialize`.
116
+ * Add queue name support to Que adapter.
92
117
 
93
- *Gannon McGibbon*
118
+ *Brad Nauta*, *Wojciech Wnętrzak*
94
119
 
95
- * Include deserialized arguments in job instances returned from
96
- `assert_enqueued_with` and `assert_performed_with`
120
+ * Don't run `after_enqueue` and `after_perform` callbacks if the callback chain is halted.
97
121
 
98
- *Alan Wu*
122
+ class MyJob < ApplicationJob
123
+ before_enqueue { throw(:abort) }
124
+ after_enqueue { # won't enter here anymore }
125
+ end
126
+
127
+ `after_enqueue` and `after_perform` callbacks will no longer run if the callback chain is halted.
128
+ This behaviour is a breaking change and won't take effect until Rails 6.2.
129
+ To enable this behaviour in your app right now, you can add in your app's configuration file
130
+ `config.active_job.skip_after_callbacks_if_terminated = true`.
131
+
132
+ *Edouard Chin*
133
+
134
+ * Fix enqueuing and performing incorrect logging message.
99
135
 
100
- * Increment execution count before deserialize arguments.
136
+ Jobs will no longer always log "Enqueued MyJob" or "Performed MyJob" when they actually didn't get enqueued/performed.
101
137
 
102
- Currently, the execution count increments after deserializes arguments.
103
- Therefore, if an error occurs with deserialize, it retries indefinitely.
138
+ ```ruby
139
+ class MyJob < ApplicationJob
140
+ before_enqueue { throw(:abort) }
141
+ end
104
142
 
105
- *Yuji Yaginuma*
143
+ MyJob.perform_later # Will no longer log "Enqueued MyJob" since job wasn't even enqueued through adapter.
144
+ ```
106
145
 
146
+ A new message will be logged in case a job couldn't be enqueued, either because the callback chain was halted or
147
+ because an exception happened during enqueuing. (i.e. Redis is down when you try to enqueue your job)
107
148
 
108
- ## Rails 5.2.1.1 (November 27, 2018) ##
149
+ *Edouard Chin*
109
150
 
110
- * Do not deserialize GlobalID objects that were not generated by Active Job.
151
+ * Add an option to disable logging of the job arguments when enqueuing and executing the job.
111
152
 
112
- Trusting any GlobaID object when deserializing jobs can allow attackers to access
113
- information that should not be accessible to them.
153
+ class SensitiveJob < ApplicationJob
154
+ self.log_arguments = false
155
+
156
+ def perform(my_sensitive_argument)
157
+ end
158
+ end
114
159
 
115
- Fix CVE-2018-16476.
160
+ When dealing with sensitive arguments as password and tokens it is now possible to configure the job
161
+ to not put the sensitive argument in the logs.
116
162
 
117
163
  *Rafael Mendonça França*
118
164
 
165
+ * Changes in `queue_name_prefix` of a job no longer affects all other jobs.
119
166
 
120
- ## Rails 5.2.1 (August 07, 2018) ##
167
+ Fixes #37084.
121
168
 
122
- * Pass the error instance as the second parameter of block executed by `discard_on`.
169
+ *Lucas Mansur*
123
170
 
124
- Fixes #32853.
171
+ * Allow `Class` and `Module` instances to be serialized.
125
172
 
126
- *Yuji Yaginuma*
173
+ *Kevin Deisz*
127
174
 
128
- ## Rails 5.2.0 (April 09, 2018) ##
175
+ * Log potential matches in `assert_enqueued_with` and `assert_performed_with`.
129
176
 
130
- * Allow block to be passed to `ActiveJob::Base.discard_on` to allow custom handling of discard jobs.
177
+ *Gareth du Plooy*
131
178
 
132
- Example:
179
+ * Add `at` argument to the `perform_enqueued_jobs` test helper.
133
180
 
134
- class RemoteServiceJob < ActiveJob::Base
135
- discard_on(CustomAppException) do |job, exception|
136
- ExceptionNotifier.caught(exception)
137
- end
181
+ *John Crepezzi*, *Eileen Uchitelle*
138
182
 
139
- def perform(*args)
140
- # Might raise CustomAppException for something domain specific
141
- end
142
- end
183
+ * `assert_enqueued_with` and `assert_performed_with` can now test jobs with relative delay.
184
+
185
+ *Vlado Cingel*
186
+
187
+ * Add jitter to `ActiveJob::Exceptions.retry_on`.
188
+
189
+ `ActiveJob::Exceptions.retry_on` now uses a random amount of jitter in order to
190
+ prevent the [thundering herd effect](https://en.wikipedia.org/wiki/Thundering_herd_problem). Defaults to
191
+ 15% (represented as 0.15) but overridable via the `:jitter` option when using `retry_on`.
192
+ Jitter is applied when an `Integer`, `ActiveSupport::Duration` or `:exponentially_longer`, is passed to the `wait` argument in `retry_on`.
143
193
 
144
- *Aidan Haran*
194
+ ```ruby
195
+ retry_on(MyError, wait: :exponentially_longer, jitter: 0.30)
196
+ ```
145
197
 
146
- * Support redis-rb 4.0.
198
+ *Anthony Ross*
147
199
 
148
- *Jeremy Daer*
149
200
 
150
- Please check [5-1-stable](https://github.com/rails/rails/blob/5-1-stable/activejob/CHANGELOG.md) for previous changes.
201
+ Please check [6-0-stable](https://github.com/rails/rails/blob/6-0-stable/activejob/CHANGELOG.md) for previous changes.
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014-2018 David Heinemeier Hansson
1
+ Copyright (c) 2014-2020 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
@@ -1,7 +1,7 @@
1
- # Active Job -- Make work happen later
1
+ # Active Job Make work happen later
2
2
 
3
3
  Active Job is a framework for declaring jobs and making them run on a variety
4
- of queueing backends. These jobs can be everything from regularly scheduled
4
+ of queuing backends. These jobs can be everything from regularly scheduled
5
5
  clean-ups, to billing charges, to mailings. Anything that can be chopped up into
6
6
  small units of work and run in parallel, really.
7
7
 
@@ -17,12 +17,13 @@ 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
21
 
21
22
  ## Usage
22
23
 
23
- To learn how to use your preferred queueing backend see its adapter
24
+ To learn how to use your preferred queuing backend see its adapter
24
25
  documentation at
25
- [ActiveJob::QueueAdapters](http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html).
26
+ [ActiveJob::QueueAdapters](https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html).
26
27
 
27
28
  Declare a job like so:
28
29
 
@@ -39,7 +40,7 @@ end
39
40
  Enqueue a job like so:
40
41
 
41
42
  ```ruby
42
- MyJob.perform_later record # Enqueue a job to be performed as soon as the queueing system is free.
43
+ MyJob.perform_later record # Enqueue a job to be performed as soon as the queuing system is free.
43
44
  ```
44
45
 
45
46
  ```ruby
@@ -82,15 +83,18 @@ This works with any class that mixes in GlobalID::Identification, which
82
83
  by default has been mixed into Active Record classes.
83
84
 
84
85
 
85
- ## Supported queueing systems
86
+ ## Supported queuing systems
86
87
 
87
- Active Job has built-in adapters for multiple queueing backends (Sidekiq,
88
+ Active Job has built-in adapters for multiple queuing backends (Sidekiq,
88
89
  Resque, Delayed Job and others). To get an up-to-date list of the adapters
89
- see the API Documentation for [ActiveJob::QueueAdapters](http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html).
90
+ see the API Documentation for [ActiveJob::QueueAdapters](https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html).
90
91
 
91
- ## Auxiliary gems
92
+ **Please note:** We are not accepting pull requests for new adapters. We
93
+ encourage library authors to provide an ActiveJob adapter as part of
94
+ their gem, or as a stand-alone gem. For discussion about this see the
95
+ following PRs: [23311](https://github.com/rails/rails/issues/23311#issuecomment-176275718),
96
+ [21406](https://github.com/rails/rails/pull/21406#issuecomment-138813484), and [#32285](https://github.com/rails/rails/pull/32285).
92
97
 
93
- * [activejob-stats](https://github.com/seuros/activejob-stats)
94
98
 
95
99
  ## Download and installation
96
100
 
@@ -102,7 +106,8 @@ The latest version of Active Job can be installed with RubyGems:
102
106
 
103
107
  Source code can be downloaded as part of the Rails project on GitHub:
104
108
 
105
- * https://github.com/rails/rails/tree/5-2-stable/activejob
109
+ * https://github.com/rails/rails/tree/main/activejob
110
+
106
111
 
107
112
  ## License
108
113
 
@@ -115,7 +120,7 @@ Active Job is released under the MIT license:
115
120
 
116
121
  API documentation is at:
117
122
 
118
- * http://api.rubyonrails.org
123
+ * https://api.rubyonrails.org
119
124
 
120
125
  Bug reports for the Ruby on Rails project can be filed here:
121
126
 
@@ -123,4 +128,4 @@ Bug reports for the Ruby on Rails project can be filed here:
123
128
 
124
129
  Feature requests should be discussed on the rails-core mailing list here:
125
130
 
126
- * https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
131
+ * https://discuss.rubyonrails.org/c/rubyonrails-core
@@ -14,29 +14,30 @@ module ActiveJob
14
14
  end
15
15
 
16
16
  # Raised when an unsupported argument type is set as a job argument. We
17
- # currently support NilClass, Integer, Fixnum, Float, String, TrueClass, FalseClass,
18
- # Bignum, BigDecimal, and objects that can be represented as GlobalIDs (ex: Active Record).
17
+ # currently support String, Integer, Float, NilClass, TrueClass, FalseClass,
18
+ # BigDecimal, Symbol, Date, Time, DateTime, ActiveSupport::TimeWithZone,
19
+ # ActiveSupport::Duration, Hash, ActiveSupport::HashWithIndifferentAccess,
20
+ # Array or GlobalID::Identification instances, although this can be extended
21
+ # by adding custom serializers.
19
22
  # Raised if you set the key for a Hash something else than a string or
20
23
  # a symbol. Also raised when trying to serialize an object which can't be
21
- # identified with a Global ID - such as an unpersisted Active Record model.
24
+ # identified with a GlobalID - such as an unpersisted Active Record model.
22
25
  class SerializationError < ArgumentError; end
23
26
 
24
27
  module Arguments
25
28
  extend self
26
- # :nodoc:
27
- TYPE_WHITELIST = [ NilClass, String, Integer, Float, BigDecimal, TrueClass, FalseClass ]
28
- TYPE_WHITELIST.push(Fixnum, Bignum) unless 1.class == Integer
29
-
30
- # Serializes a set of arguments. Whitelisted types are returned
31
- # as-is. Arrays/Hashes are serialized element by element.
32
- # All other types are serialized using GlobalID.
29
+ # Serializes a set of arguments. Intrinsic types that can safely be
30
+ # serialized without mutation are returned as-is. Arrays/Hashes are
31
+ # serialized element by element. All other types are serialized using
32
+ # GlobalID.
33
33
  def serialize(arguments)
34
34
  arguments.map { |argument| serialize_argument(argument) }
35
35
  end
36
36
 
37
- # Deserializes a set of arguments. Whitelisted types are returned
38
- # as-is. Arrays/Hashes are deserialized element by element.
39
- # All other types are deserialized using GlobalID.
37
+ # Deserializes a set of arguments. Intrinsic types that can safely be
38
+ # deserialized without mutation are returned as-is. Arrays/Hashes are
39
+ # deserialized element by element. All other types are deserialized using
40
+ # GlobalID.
40
41
  def deserialize(arguments)
41
42
  arguments.map { |argument| deserialize_argument(argument) }
42
43
  rescue
@@ -45,16 +46,59 @@ module ActiveJob
45
46
 
46
47
  private
47
48
  # :nodoc:
48
- GLOBALID_KEY = "_aj_globalid".freeze
49
+ PERMITTED_TYPES = [ NilClass, String, Integer, Float, BigDecimal, TrueClass, FalseClass ]
50
+ # :nodoc:
51
+ GLOBALID_KEY = "_aj_globalid"
52
+ # :nodoc:
53
+ SYMBOL_KEYS_KEY = "_aj_symbol_keys"
54
+ # :nodoc:
55
+ RUBY2_KEYWORDS_KEY = "_aj_ruby2_keywords"
49
56
  # :nodoc:
50
- SYMBOL_KEYS_KEY = "_aj_symbol_keys".freeze
57
+ WITH_INDIFFERENT_ACCESS_KEY = "_aj_hash_with_indifferent_access"
51
58
  # :nodoc:
52
- WITH_INDIFFERENT_ACCESS_KEY = "_aj_hash_with_indifferent_access".freeze
53
- private_constant :GLOBALID_KEY, :SYMBOL_KEYS_KEY, :WITH_INDIFFERENT_ACCESS_KEY
59
+ OBJECT_SERIALIZER_KEY = "_aj_serialized"
60
+
61
+ # :nodoc:
62
+ RESERVED_KEYS = [
63
+ GLOBALID_KEY, GLOBALID_KEY.to_sym,
64
+ SYMBOL_KEYS_KEY, SYMBOL_KEYS_KEY.to_sym,
65
+ RUBY2_KEYWORDS_KEY, RUBY2_KEYWORDS_KEY.to_sym,
66
+ OBJECT_SERIALIZER_KEY, OBJECT_SERIALIZER_KEY.to_sym,
67
+ WITH_INDIFFERENT_ACCESS_KEY, WITH_INDIFFERENT_ACCESS_KEY.to_sym,
68
+ ]
69
+ private_constant :PERMITTED_TYPES, :RESERVED_KEYS, :GLOBALID_KEY,
70
+ :SYMBOL_KEYS_KEY, :RUBY2_KEYWORDS_KEY, :WITH_INDIFFERENT_ACCESS_KEY
71
+
72
+ unless Hash.respond_to?(:ruby2_keywords_hash?) && Hash.respond_to?(:ruby2_keywords_hash)
73
+ using Module.new {
74
+ refine Hash do
75
+ class << Hash
76
+ if RUBY_VERSION >= "2.7"
77
+ def ruby2_keywords_hash?(hash)
78
+ !new(*[hash]).default.equal?(hash)
79
+ end
80
+ else
81
+ def ruby2_keywords_hash?(hash)
82
+ false
83
+ end
84
+ end
85
+
86
+ def ruby2_keywords_hash(hash)
87
+ _ruby2_keywords_hash(**hash)
88
+ end
89
+
90
+ private def _ruby2_keywords_hash(*args)
91
+ args.last
92
+ end
93
+ ruby2_keywords(:_ruby2_keywords_hash) if respond_to?(:ruby2_keywords, true)
94
+ end
95
+ end
96
+ }
97
+ end
54
98
 
55
99
  def serialize_argument(argument)
56
100
  case argument
57
- when *TYPE_WHITELIST
101
+ when *PERMITTED_TYPES
58
102
  argument
59
103
  when GlobalID::Identification
60
104
  convert_to_global_id_hash(argument)
@@ -63,14 +107,19 @@ module ActiveJob
63
107
  when ActiveSupport::HashWithIndifferentAccess
64
108
  serialize_indifferent_hash(argument)
65
109
  when Hash
66
- symbol_keys = argument.each_key.grep(Symbol).map(&:to_s)
110
+ symbol_keys = argument.each_key.grep(Symbol).map!(&:to_s)
111
+ aj_hash_key = if Hash.ruby2_keywords_hash?(argument)
112
+ RUBY2_KEYWORDS_KEY
113
+ else
114
+ SYMBOL_KEYS_KEY
115
+ end
67
116
  result = serialize_hash(argument)
68
- result[SYMBOL_KEYS_KEY] = symbol_keys
117
+ result[aj_hash_key] = symbol_keys
69
118
  result
70
119
  when -> (arg) { arg.respond_to?(:permitted?) }
71
120
  serialize_indifferent_hash(argument.to_h)
72
121
  else
73
- raise SerializationError.new("Unsupported argument type: #{argument.class.name}")
122
+ Serializers.serialize(argument)
74
123
  end
75
124
  end
76
125
 
@@ -78,13 +127,15 @@ module ActiveJob
78
127
  case argument
79
128
  when String
80
129
  argument
81
- when *TYPE_WHITELIST
130
+ when *PERMITTED_TYPES
82
131
  argument
83
132
  when Array
84
133
  argument.map { |arg| deserialize_argument(arg) }
85
134
  when Hash
86
135
  if serialized_global_id?(argument)
87
136
  deserialize_global_id argument
137
+ elsif custom_serialized?(argument)
138
+ Serializers.deserialize(argument)
88
139
  else
89
140
  deserialize_hash(argument)
90
141
  end
@@ -101,6 +152,10 @@ module ActiveJob
101
152
  GlobalID::Locator.locate hash[GLOBALID_KEY]
102
153
  end
103
154
 
155
+ def custom_serialized?(hash)
156
+ hash.key?(OBJECT_SERIALIZER_KEY)
157
+ end
158
+
104
159
  def serialize_hash(argument)
105
160
  argument.each_with_object({}) do |(key, value), hash|
106
161
  hash[serialize_hash_key(key)] = serialize_argument(value)
@@ -113,18 +168,13 @@ module ActiveJob
113
168
  result = result.with_indifferent_access
114
169
  elsif symbol_keys = result.delete(SYMBOL_KEYS_KEY)
115
170
  result = transform_symbol_keys(result, symbol_keys)
171
+ elsif symbol_keys = result.delete(RUBY2_KEYWORDS_KEY)
172
+ result = transform_symbol_keys(result, symbol_keys)
173
+ result = Hash.ruby2_keywords_hash(result)
116
174
  end
117
175
  result
118
176
  end
119
177
 
120
- # :nodoc:
121
- RESERVED_KEYS = [
122
- GLOBALID_KEY, GLOBALID_KEY.to_sym,
123
- SYMBOL_KEYS_KEY, SYMBOL_KEYS_KEY.to_sym,
124
- WITH_INDIFFERENT_ACCESS_KEY, WITH_INDIFFERENT_ACCESS_KEY.to_sym,
125
- ]
126
- private_constant :RESERVED_KEYS
127
-
128
178
  def serialize_hash_key(key)
129
179
  case key
130
180
  when *RESERVED_KEYS
@@ -8,7 +8,10 @@ require "active_job/enqueuing"
8
8
  require "active_job/execution"
9
9
  require "active_job/callbacks"
10
10
  require "active_job/exceptions"
11
+ require "active_job/log_subscriber"
11
12
  require "active_job/logging"
13
+ require "active_job/instrumentation"
14
+ require "active_job/timezones"
12
15
  require "active_job/translation"
13
16
 
14
17
  module ActiveJob #:nodoc:
@@ -39,7 +42,7 @@ module ActiveJob #:nodoc:
39
42
  # Records that are passed in are serialized/deserialized using Global
40
43
  # ID. More information can be found in Arguments.
41
44
  #
42
- # To enqueue a job to be performed as soon as the queueing system is free:
45
+ # To enqueue a job to be performed as soon as the queuing system is free:
43
46
  #
44
47
  # ProcessPhotoJob.perform_later(photo)
45
48
  #
@@ -67,6 +70,8 @@ module ActiveJob #:nodoc:
67
70
  include Callbacks
68
71
  include Exceptions
69
72
  include Logging
73
+ include Instrumentation
74
+ include Timezones
70
75
  include Translation
71
76
 
72
77
  ActiveSupport.run_load_hooks(:active_job, self)
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/callbacks"
4
+ require "active_support/core_ext/object/with_options"
5
+ require "active_support/core_ext/module/attribute_accessors"
4
6
 
5
7
  module ActiveJob
6
8
  # = Active Job Callbacks
@@ -27,13 +29,25 @@ module ActiveJob
27
29
  end
28
30
 
29
31
  included do
30
- define_callbacks :perform
31
- define_callbacks :enqueue
32
+ class_attribute :return_false_on_aborted_enqueue, instance_accessor: false, instance_predicate: false, default: false
33
+ singleton_class.deprecate :return_false_on_aborted_enqueue, :return_false_on_aborted_enqueue=
34
+ cattr_accessor :skip_after_callbacks_if_terminated, instance_accessor: false, default: false
35
+
36
+ with_options(skip_after_callbacks_if_terminated: skip_after_callbacks_if_terminated) do
37
+ define_callbacks :perform
38
+ define_callbacks :enqueue
39
+ end
32
40
  end
33
41
 
34
42
  # These methods will be included into any Active Job object, adding
35
43
  # callbacks for +perform+ and +enqueue+ methods.
36
44
  module ClassMethods
45
+ def inherited(klass)
46
+ klass.get_callbacks(:enqueue).config[:skip_after_callbacks_if_terminated] = skip_after_callbacks_if_terminated
47
+ klass.get_callbacks(:perform).config[:skip_after_callbacks_if_terminated] = skip_after_callbacks_if_terminated
48
+ super
49
+ end
50
+
37
51
  # Defines a callback that will get called right before the
38
52
  # job's perform method is executed.
39
53
  #
@@ -88,6 +102,19 @@ module ActiveJob
88
102
  # end
89
103
  # end
90
104
  #
105
+ # You can access the return value of the job only if the execution wasn't halted.
106
+ #
107
+ # class VideoProcessJob < ActiveJob::Base
108
+ # around_perform do |job, block|
109
+ # value = block.call
110
+ # puts value # => "Hello World!"
111
+ # end
112
+ #
113
+ # def perform
114
+ # "Hello World!"
115
+ # end
116
+ # end
117
+ #
91
118
  def around_perform(*filters, &blk)
92
119
  set_callback(:perform, :around, *filters, &blk)
93
120
  end
@@ -130,7 +157,7 @@ module ActiveJob
130
157
  set_callback(:enqueue, :after, *filters, &blk)
131
158
  end
132
159
 
133
- # Defines a callback that will get called around the enqueueing
160
+ # Defines a callback that will get called around the enqueuing
134
161
  # of the job.
135
162
  #
136
163
  # class VideoProcessJob < ActiveJob::Base
@@ -151,5 +178,21 @@ module ActiveJob
151
178
  set_callback(:enqueue, :around, *filters, &blk)
152
179
  end
153
180
  end
181
+
182
+ private
183
+ def halted_callback_hook(_filter, name) # :nodoc:
184
+ return super unless %i(enqueue perform).include?(name.to_sym)
185
+ callbacks = public_send("_#{name}_callbacks")
186
+
187
+ if !self.class.skip_after_callbacks_if_terminated && callbacks.any? { |c| c.kind == :after }
188
+ ActiveSupport::Deprecation.warn(<<~EOM)
189
+ In Rails 6.2, `after_enqueue`/`after_perform` callbacks no longer run if `before_enqueue`/`before_perform` respectively halts with `throw :abort`.
190
+ To enable this behavior, uncomment the `config.active_job.skip_after_callbacks_if_terminated` config
191
+ in the new 6.1 framework defaults initializer.
192
+ EOM
193
+ end
194
+
195
+ super
196
+ end
154
197
  end
155
198
  end
@@ -10,9 +10,11 @@ module ActiveJob
10
10
  def perform_now(*args)
11
11
  @job_class.new(*args).perform_now
12
12
  end
13
+ ruby2_keywords(:perform_now) if respond_to?(:ruby2_keywords, true)
13
14
 
14
15
  def perform_later(*args)
15
16
  @job_class.new(*args).enqueue @options
16
17
  end
18
+ ruby2_keywords(:perform_later) if respond_to?(:ruby2_keywords, true)
17
19
  end
18
20
  end