activejob 5.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +80 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.md +126 -0
  5. data/lib/active_job.rb +39 -0
  6. data/lib/active_job/arguments.rb +165 -0
  7. data/lib/active_job/base.rb +74 -0
  8. data/lib/active_job/callbacks.rb +155 -0
  9. data/lib/active_job/configured_job.rb +18 -0
  10. data/lib/active_job/core.rb +158 -0
  11. data/lib/active_job/enqueuing.rb +59 -0
  12. data/lib/active_job/exceptions.rb +134 -0
  13. data/lib/active_job/execution.rb +49 -0
  14. data/lib/active_job/gem_version.rb +17 -0
  15. data/lib/active_job/logging.rb +130 -0
  16. data/lib/active_job/queue_adapter.rb +60 -0
  17. data/lib/active_job/queue_adapters.rb +139 -0
  18. data/lib/active_job/queue_adapters/async_adapter.rb +116 -0
  19. data/lib/active_job/queue_adapters/backburner_adapter.rb +36 -0
  20. data/lib/active_job/queue_adapters/delayed_job_adapter.rb +47 -0
  21. data/lib/active_job/queue_adapters/inline_adapter.rb +23 -0
  22. data/lib/active_job/queue_adapters/qu_adapter.rb +46 -0
  23. data/lib/active_job/queue_adapters/que_adapter.rb +39 -0
  24. data/lib/active_job/queue_adapters/queue_classic_adapter.rb +58 -0
  25. data/lib/active_job/queue_adapters/resque_adapter.rb +53 -0
  26. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +47 -0
  27. data/lib/active_job/queue_adapters/sneakers_adapter.rb +48 -0
  28. data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +49 -0
  29. data/lib/active_job/queue_adapters/test_adapter.rb +67 -0
  30. data/lib/active_job/queue_name.rb +49 -0
  31. data/lib/active_job/queue_priority.rb +43 -0
  32. data/lib/active_job/railtie.rb +34 -0
  33. data/lib/active_job/test_case.rb +11 -0
  34. data/lib/active_job/test_helper.rb +456 -0
  35. data/lib/active_job/translation.rb +13 -0
  36. data/lib/active_job/version.rb +10 -0
  37. data/lib/rails/generators/job/job_generator.rb +40 -0
  38. data/lib/rails/generators/job/templates/application_job.rb.tt +9 -0
  39. data/lib/rails/generators/job/templates/job.rb.tt +9 -0
  40. metadata +110 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ac0f259222beb53e1a8a570a52df3de03d523fcf059895581cf7196ae08770c4
4
+ data.tar.gz: 8219f2409dbdb380a959e43e17fb0a03e0711ec11c9b006a7e600f21704cdf79
5
+ SHA512:
6
+ metadata.gz: f16d9531ea070183270cb6917914a66deaf20b164190a00393de34bf5f46ee107830c9f3ab3e6d9232248cbe2fbc498680060dddbbb23deddf6c766ddd511bca
7
+ data.tar.gz: 2e016b400decfe1a590c194d931d05b33699ec15ae6708803b6da41f7db3c69a86af84f63cee9af45b0334d98c6dfe806455557ab2a4e4ea621e969d068ec6f1
@@ -0,0 +1,80 @@
1
+ ## Rails 5.2.3 (March 27, 2019) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 5.2.2.1 (March 11, 2019) ##
7
+
8
+ * No changes.
9
+
10
+
11
+ ## Rails 5.2.2 (December 04, 2018) ##
12
+
13
+ * Make sure `assert_enqueued_with()` & `assert_performed_with()` work reliably with hash arguments.
14
+
15
+ *Sharang Dashputre*
16
+
17
+ * Restore `ActionController::Parameters` support to `ActiveJob::Arguments.serialize`.
18
+
19
+ *Bernie Chiu*
20
+
21
+ * Restore `HashWithIndifferentAccess` support to `ActiveJob::Arguments.deserialize`.
22
+
23
+ *Gannon McGibbon*
24
+
25
+ * Include deserialized arguments in job instances returned from
26
+ `assert_enqueued_with` and `assert_performed_with`
27
+
28
+ *Alan Wu*
29
+
30
+ * Increment execution count before deserialize arguments.
31
+
32
+ Currently, the execution count increments after deserializes arguments.
33
+ Therefore, if an error occurs with deserialize, it retries indefinitely.
34
+
35
+ *Yuji Yaginuma*
36
+
37
+
38
+ ## Rails 5.2.1.1 (November 27, 2018) ##
39
+
40
+ * Do not deserialize GlobalID objects that were not generated by Active Job.
41
+
42
+ Trusting any GlobaID object when deserializing jobs can allow attackers to access
43
+ information that should not be accessible to them.
44
+
45
+ Fix CVE-2018-16476.
46
+
47
+ *Rafael Mendonça França*
48
+
49
+
50
+ ## Rails 5.2.1 (August 07, 2018) ##
51
+
52
+ * Pass the error instance as the second parameter of block executed by `discard_on`.
53
+
54
+ Fixes #32853.
55
+
56
+ *Yuji Yaginuma*
57
+
58
+ ## Rails 5.2.0 (April 09, 2018) ##
59
+
60
+ * Allow block to be passed to `ActiveJob::Base.discard_on` to allow custom handling of discard jobs.
61
+
62
+ Example:
63
+
64
+ class RemoteServiceJob < ActiveJob::Base
65
+ discard_on(CustomAppException) do |job, exception|
66
+ ExceptionNotifier.caught(exception)
67
+ end
68
+
69
+ def perform(*args)
70
+ # Might raise CustomAppException for something domain specific
71
+ end
72
+ end
73
+
74
+ *Aidan Haran*
75
+
76
+ * Support redis-rb 4.0.
77
+
78
+ *Jeremy Daer*
79
+
80
+ Please check [5-1-stable](https://github.com/rails/rails/blob/5-1-stable/activejob/CHANGELOG.md) for previous changes.
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2014-2018 David Heinemeier Hansson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
@@ -0,0 +1,126 @@
1
+ # Active Job -- Make work happen later
2
+
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
5
+ clean-ups, to billing charges, to mailings. Anything that can be chopped up into
6
+ small units of work and run in parallel, really.
7
+
8
+ It also serves as the backend for Action Mailer's #deliver_later functionality
9
+ that makes it easy to turn any mailing into a job for running later. That's
10
+ one of the most common jobs in a modern web application: sending emails outside
11
+ of the request-response cycle, so the user doesn't have to wait on it.
12
+
13
+ The main point is to ensure that all Rails apps will have a job infrastructure
14
+ in place, even if it's in the form of an "immediate runner". We can then have
15
+ framework features and other gems build on top of that, without having to worry
16
+ about API differences between Delayed Job and Resque. Picking your queuing
17
+ backend becomes more of an operational concern, then. And you'll be able to
18
+ switch between them without having to rewrite your jobs.
19
+
20
+
21
+ ## Usage
22
+
23
+ To learn how to use your preferred queueing backend see its adapter
24
+ documentation at
25
+ [ActiveJob::QueueAdapters](http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html).
26
+
27
+ Declare a job like so:
28
+
29
+ ```ruby
30
+ class MyJob < ActiveJob::Base
31
+ queue_as :my_jobs
32
+
33
+ def perform(record)
34
+ record.do_work
35
+ end
36
+ end
37
+ ```
38
+
39
+ Enqueue a job like so:
40
+
41
+ ```ruby
42
+ MyJob.perform_later record # Enqueue a job to be performed as soon as the queueing system is free.
43
+ ```
44
+
45
+ ```ruby
46
+ MyJob.set(wait_until: Date.tomorrow.noon).perform_later(record) # Enqueue a job to be performed tomorrow at noon.
47
+ ```
48
+
49
+ ```ruby
50
+ MyJob.set(wait: 1.week).perform_later(record) # Enqueue a job to be performed 1 week from now.
51
+ ```
52
+
53
+ That's it!
54
+
55
+
56
+ ## GlobalID support
57
+
58
+ Active Job supports [GlobalID serialization](https://github.com/rails/globalid/) for parameters. This makes it possible
59
+ to pass live Active Record objects to your job instead of class/id pairs, which
60
+ you then have to manually deserialize. Before, jobs would look like this:
61
+
62
+ ```ruby
63
+ class TrashableCleanupJob
64
+ def perform(trashable_class, trashable_id, depth)
65
+ trashable = trashable_class.constantize.find(trashable_id)
66
+ trashable.cleanup(depth)
67
+ end
68
+ end
69
+ ```
70
+
71
+ Now you can simply do:
72
+
73
+ ```ruby
74
+ class TrashableCleanupJob
75
+ def perform(trashable, depth)
76
+ trashable.cleanup(depth)
77
+ end
78
+ end
79
+ ```
80
+
81
+ This works with any class that mixes in GlobalID::Identification, which
82
+ by default has been mixed into Active Record classes.
83
+
84
+
85
+ ## Supported queueing systems
86
+
87
+ Active Job has built-in adapters for multiple queueing backends (Sidekiq,
88
+ 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
+
91
+ ## Auxiliary gems
92
+
93
+ * [activejob-stats](https://github.com/seuros/activejob-stats)
94
+
95
+ ## Download and installation
96
+
97
+ The latest version of Active Job can be installed with RubyGems:
98
+
99
+ ```
100
+ $ gem install activejob
101
+ ```
102
+
103
+ Source code can be downloaded as part of the Rails project on GitHub:
104
+
105
+ * https://github.com/rails/rails/tree/5-2-stable/activejob
106
+
107
+ ## License
108
+
109
+ Active Job is released under the MIT license:
110
+
111
+ * https://opensource.org/licenses/MIT
112
+
113
+
114
+ ## Support
115
+
116
+ API documentation is at:
117
+
118
+ * http://api.rubyonrails.org
119
+
120
+ Bug reports for the Ruby on Rails project can be filed here:
121
+
122
+ * https://github.com/rails/rails/issues
123
+
124
+ Feature requests should be discussed on the rails-core mailing list here:
125
+
126
+ * https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # Copyright (c) 2014-2018 David Heinemeier Hansson
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #++
25
+
26
+ require "active_support"
27
+ require "active_support/rails"
28
+ require "active_job/version"
29
+ require "global_id"
30
+
31
+ module ActiveJob
32
+ extend ActiveSupport::Autoload
33
+
34
+ autoload :Base
35
+ autoload :QueueAdapters
36
+ autoload :ConfiguredJob
37
+ autoload :TestCase
38
+ autoload :TestHelper
39
+ end
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash"
4
+
5
+ module ActiveJob
6
+ # Raised when an exception is raised during job arguments deserialization.
7
+ #
8
+ # Wraps the original exception raised as +cause+.
9
+ class DeserializationError < StandardError
10
+ def initialize #:nodoc:
11
+ super("Error while trying to deserialize arguments: #{$!.message}")
12
+ set_backtrace $!.backtrace
13
+ end
14
+ end
15
+
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).
19
+ # Raised if you set the key for a Hash something else than a string or
20
+ # 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.
22
+ class SerializationError < ArgumentError; end
23
+
24
+ module Arguments
25
+ 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.
33
+ def serialize(arguments)
34
+ arguments.map { |argument| serialize_argument(argument) }
35
+ end
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.
40
+ def deserialize(arguments)
41
+ arguments.map { |argument| deserialize_argument(argument) }
42
+ rescue
43
+ raise DeserializationError
44
+ end
45
+
46
+ private
47
+ # :nodoc:
48
+ GLOBALID_KEY = "_aj_globalid".freeze
49
+ # :nodoc:
50
+ SYMBOL_KEYS_KEY = "_aj_symbol_keys".freeze
51
+ # :nodoc:
52
+ WITH_INDIFFERENT_ACCESS_KEY = "_aj_hash_with_indifferent_access".freeze
53
+ private_constant :GLOBALID_KEY, :SYMBOL_KEYS_KEY, :WITH_INDIFFERENT_ACCESS_KEY
54
+
55
+ def serialize_argument(argument)
56
+ case argument
57
+ when *TYPE_WHITELIST
58
+ argument
59
+ when GlobalID::Identification
60
+ convert_to_global_id_hash(argument)
61
+ when Array
62
+ argument.map { |arg| serialize_argument(arg) }
63
+ when ActiveSupport::HashWithIndifferentAccess
64
+ serialize_indifferent_hash(argument)
65
+ when Hash
66
+ symbol_keys = argument.each_key.grep(Symbol).map(&:to_s)
67
+ result = serialize_hash(argument)
68
+ result[SYMBOL_KEYS_KEY] = symbol_keys
69
+ result
70
+ when -> (arg) { arg.respond_to?(:permitted?) }
71
+ serialize_indifferent_hash(argument.to_h)
72
+ else
73
+ raise SerializationError.new("Unsupported argument type: #{argument.class.name}")
74
+ end
75
+ end
76
+
77
+ def deserialize_argument(argument)
78
+ case argument
79
+ when String
80
+ argument
81
+ when *TYPE_WHITELIST
82
+ argument
83
+ when Array
84
+ argument.map { |arg| deserialize_argument(arg) }
85
+ when Hash
86
+ if serialized_global_id?(argument)
87
+ deserialize_global_id argument
88
+ else
89
+ deserialize_hash(argument)
90
+ end
91
+ else
92
+ raise ArgumentError, "Can only deserialize primitive arguments: #{argument.inspect}"
93
+ end
94
+ end
95
+
96
+ def serialized_global_id?(hash)
97
+ hash.size == 1 && hash.include?(GLOBALID_KEY)
98
+ end
99
+
100
+ def deserialize_global_id(hash)
101
+ GlobalID::Locator.locate hash[GLOBALID_KEY]
102
+ end
103
+
104
+ def serialize_hash(argument)
105
+ argument.each_with_object({}) do |(key, value), hash|
106
+ hash[serialize_hash_key(key)] = serialize_argument(value)
107
+ end
108
+ end
109
+
110
+ def deserialize_hash(serialized_hash)
111
+ result = serialized_hash.transform_values { |v| deserialize_argument(v) }
112
+ if result.delete(WITH_INDIFFERENT_ACCESS_KEY)
113
+ result = result.with_indifferent_access
114
+ elsif symbol_keys = result.delete(SYMBOL_KEYS_KEY)
115
+ result = transform_symbol_keys(result, symbol_keys)
116
+ end
117
+ result
118
+ end
119
+
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
+ def serialize_hash_key(key)
129
+ case key
130
+ when *RESERVED_KEYS
131
+ raise SerializationError.new("Can't serialize a Hash with reserved key #{key.inspect}")
132
+ when String, Symbol
133
+ key.to_s
134
+ else
135
+ raise SerializationError.new("Only string and symbol hash keys may be serialized as job arguments, but #{key.inspect} is a #{key.class}")
136
+ end
137
+ end
138
+
139
+ def serialize_indifferent_hash(indifferent_hash)
140
+ result = serialize_hash(indifferent_hash)
141
+ result[WITH_INDIFFERENT_ACCESS_KEY] = serialize_argument(true)
142
+ result
143
+ end
144
+
145
+ def transform_symbol_keys(hash, symbol_keys)
146
+ # NOTE: HashWithIndifferentAccess#transform_keys always
147
+ # returns stringified keys with indifferent access
148
+ # so we call #to_h here to ensure keys are symbolized.
149
+ hash.to_h.transform_keys do |key|
150
+ if symbol_keys.include?(key)
151
+ key.to_sym
152
+ else
153
+ key
154
+ end
155
+ end
156
+ end
157
+
158
+ def convert_to_global_id_hash(argument)
159
+ { GLOBALID_KEY => argument.to_global_id.to_s }
160
+ rescue URI::GID::MissingModelIdError
161
+ raise SerializationError, "Unable to serialize #{argument.class} " \
162
+ "without an id. (Maybe you forgot to call save?)"
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_job/core"
4
+ require "active_job/queue_adapter"
5
+ require "active_job/queue_name"
6
+ require "active_job/queue_priority"
7
+ require "active_job/enqueuing"
8
+ require "active_job/execution"
9
+ require "active_job/callbacks"
10
+ require "active_job/exceptions"
11
+ require "active_job/logging"
12
+ require "active_job/translation"
13
+
14
+ module ActiveJob #:nodoc:
15
+ # = Active Job
16
+ #
17
+ # Active Job objects can be configured to work with different backend
18
+ # queuing frameworks. To specify a queue adapter to use:
19
+ #
20
+ # ActiveJob::Base.queue_adapter = :inline
21
+ #
22
+ # A list of supported adapters can be found in QueueAdapters.
23
+ #
24
+ # Active Job objects can be defined by creating a class that inherits
25
+ # from the ActiveJob::Base class. The only necessary method to
26
+ # implement is the "perform" method.
27
+ #
28
+ # To define an Active Job object:
29
+ #
30
+ # class ProcessPhotoJob < ActiveJob::Base
31
+ # def perform(photo)
32
+ # photo.watermark!('Rails')
33
+ # photo.rotate!(90.degrees)
34
+ # photo.resize_to_fit!(300, 300)
35
+ # photo.upload!
36
+ # end
37
+ # end
38
+ #
39
+ # Records that are passed in are serialized/deserialized using Global
40
+ # ID. More information can be found in Arguments.
41
+ #
42
+ # To enqueue a job to be performed as soon as the queueing system is free:
43
+ #
44
+ # ProcessPhotoJob.perform_later(photo)
45
+ #
46
+ # To enqueue a job to be processed at some point in the future:
47
+ #
48
+ # ProcessPhotoJob.set(wait_until: Date.tomorrow.noon).perform_later(photo)
49
+ #
50
+ # More information can be found in ActiveJob::Core::ClassMethods#set
51
+ #
52
+ # A job can also be processed immediately without sending to the queue:
53
+ #
54
+ # ProcessPhotoJob.perform_now(photo)
55
+ #
56
+ # == Exceptions
57
+ #
58
+ # * DeserializationError - Error class for deserialization errors.
59
+ # * SerializationError - Error class for serialization errors.
60
+ class Base
61
+ include Core
62
+ include QueueAdapter
63
+ include QueueName
64
+ include QueuePriority
65
+ include Enqueuing
66
+ include Execution
67
+ include Callbacks
68
+ include Exceptions
69
+ include Logging
70
+ include Translation
71
+
72
+ ActiveSupport.run_load_hooks(:active_job, self)
73
+ end
74
+ end