activejob 5.2.3

Sign up to get free protection for your applications and to get access to all the features.
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