omg-activejob 8.0.0.alpha1

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 (56) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +10 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.md +131 -0
  5. data/lib/active_job/arguments.rb +197 -0
  6. data/lib/active_job/base.rb +79 -0
  7. data/lib/active_job/callbacks.rb +167 -0
  8. data/lib/active_job/configured_job.rb +22 -0
  9. data/lib/active_job/core.rb +202 -0
  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 +141 -0
  13. data/lib/active_job/exceptions.rb +206 -0
  14. data/lib/active_job/execution.rb +72 -0
  15. data/lib/active_job/gem_version.rb +17 -0
  16. data/lib/active_job/instrumentation.rb +52 -0
  17. data/lib/active_job/log_subscriber.rb +226 -0
  18. data/lib/active_job/logging.rb +49 -0
  19. data/lib/active_job/queue_adapter.rb +77 -0
  20. data/lib/active_job/queue_adapters/abstract_adapter.rb +27 -0
  21. data/lib/active_job/queue_adapters/async_adapter.rb +116 -0
  22. data/lib/active_job/queue_adapters/backburner_adapter.rb +40 -0
  23. data/lib/active_job/queue_adapters/delayed_job_adapter.rb +67 -0
  24. data/lib/active_job/queue_adapters/inline_adapter.rb +27 -0
  25. data/lib/active_job/queue_adapters/queue_classic_adapter.rb +66 -0
  26. data/lib/active_job/queue_adapters/resque_adapter.rb +53 -0
  27. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +75 -0
  28. data/lib/active_job/queue_adapters/sneakers_adapter.rb +48 -0
  29. data/lib/active_job/queue_adapters/test_adapter.rb +94 -0
  30. data/lib/active_job/queue_adapters.rb +140 -0
  31. data/lib/active_job/queue_name.rb +68 -0
  32. data/lib/active_job/queue_priority.rb +60 -0
  33. data/lib/active_job/railtie.rb +107 -0
  34. data/lib/active_job/serializers/big_decimal_serializer.rb +22 -0
  35. data/lib/active_job/serializers/date_serializer.rb +20 -0
  36. data/lib/active_job/serializers/date_time_serializer.rb +16 -0
  37. data/lib/active_job/serializers/duration_serializer.rb +25 -0
  38. data/lib/active_job/serializers/module_serializer.rb +21 -0
  39. data/lib/active_job/serializers/object_serializer.rb +55 -0
  40. data/lib/active_job/serializers/range_serializer.rb +23 -0
  41. data/lib/active_job/serializers/symbol_serializer.rb +20 -0
  42. data/lib/active_job/serializers/time_object_serializer.rb +13 -0
  43. data/lib/active_job/serializers/time_serializer.rb +16 -0
  44. data/lib/active_job/serializers/time_with_zone_serializer.rb +25 -0
  45. data/lib/active_job/serializers.rb +72 -0
  46. data/lib/active_job/test_case.rb +11 -0
  47. data/lib/active_job/test_helper.rb +770 -0
  48. data/lib/active_job/timezones.rb +13 -0
  49. data/lib/active_job/translation.rb +13 -0
  50. data/lib/active_job/version.rb +10 -0
  51. data/lib/active_job.rb +71 -0
  52. data/lib/rails/generators/job/USAGE +19 -0
  53. data/lib/rails/generators/job/job_generator.rb +48 -0
  54. data/lib/rails/generators/job/templates/application_job.rb.tt +9 -0
  55. data/lib/rails/generators/job/templates/job.rb.tt +9 -0
  56. metadata +130 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 802ba9cb0255881dee3342c6c3f02acfff2cbcf17cb34b2c252377808e433d6b
4
+ data.tar.gz: b055d444e0fff0513ee33b289d4e600269ea3b994c5100d546b6e2c11091327b
5
+ SHA512:
6
+ metadata.gz: 99e08ad43087e35807d581c7906b1bacf2bdbd73e270175fd29b4df4fc6c18ffb32fd5360ed89b15313f4f9c2261ceb21a808de4a0e853c149e5d7e08fc42d3d
7
+ data.tar.gz: 855ef48da4071c96bbce3510e9820cc51bac73aa86f0d3f653dd4e3ea3392b451eab27d6547bad47ac68e9b13fc9fcc52847eb5e628bd8ddccb5863437b3953b
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ * Remove `sucker_punch` as an adapter option [since author himself recommends using AJ's own AsyncAdapter](https://github.com/brandonhilkert/sucker_punch?tab=readme-ov-file#faq).
2
+ If you're using this adapter, change to `adapter: async` for the same functionality.
3
+
4
+ *Dino Maric*
5
+
6
+ * Use `RAILS_MAX_THREADS` in `ActiveJob::AsyncAdapter`. If it is not set, use 5 as default.
7
+
8
+ *heka1024*
9
+
10
+ Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/activejob/CHANGELOG.md) for previous changes.
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 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
+
data/README.md ADDED
@@ -0,0 +1,131 @@
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 queuing 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.
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
+ 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
+ You can read more about Active Job in the [Active Job Basics](https://guides.rubyonrails.org/active_job_basics.html) guide.
21
+
22
+ ## Usage
23
+
24
+ To learn how to use your preferred queuing backend see its adapter
25
+ documentation at
26
+ [ActiveJob::QueueAdapters](https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html).
27
+
28
+ Declare a job like so:
29
+
30
+ ```ruby
31
+ class MyJob < ActiveJob::Base
32
+ queue_as :my_jobs
33
+
34
+ def perform(record)
35
+ record.do_work
36
+ end
37
+ end
38
+ ```
39
+
40
+ Enqueue a job like so:
41
+
42
+ ```ruby
43
+ MyJob.perform_later record # Enqueue a job to be performed as soon as the queuing system is free.
44
+ ```
45
+
46
+ ```ruby
47
+ MyJob.set(wait_until: Date.tomorrow.noon).perform_later(record) # Enqueue a job to be performed tomorrow at noon.
48
+ ```
49
+
50
+ ```ruby
51
+ MyJob.set(wait: 1.week).perform_later(record) # Enqueue a job to be performed 1 week from now.
52
+ ```
53
+
54
+ That's it!
55
+
56
+
57
+ ## GlobalID support
58
+
59
+ Active Job supports [GlobalID serialization](https://github.com/rails/globalid/) for parameters. This makes it possible
60
+ to pass live Active Record objects to your job instead of class/id pairs, which
61
+ you then have to manually deserialize. Before, jobs would look like this:
62
+
63
+ ```ruby
64
+ class TrashableCleanupJob
65
+ def perform(trashable_class, trashable_id, depth)
66
+ trashable = trashable_class.constantize.find(trashable_id)
67
+ trashable.cleanup(depth)
68
+ end
69
+ end
70
+ ```
71
+
72
+ Now you can simply do:
73
+
74
+ ```ruby
75
+ class TrashableCleanupJob
76
+ def perform(trashable, depth)
77
+ trashable.cleanup(depth)
78
+ end
79
+ end
80
+ ```
81
+
82
+ This works with any class that mixes in GlobalID::Identification, which
83
+ by default has been mixed into Active Record classes.
84
+
85
+
86
+ ## Supported queuing systems
87
+
88
+ Active Job has built-in adapters for multiple queuing backends (Sidekiq,
89
+ Resque, Delayed Job and others). To get an up-to-date list of the adapters
90
+ see the API Documentation for [ActiveJob::QueueAdapters](https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html).
91
+
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).
97
+
98
+
99
+ ## Download and installation
100
+
101
+ The latest version of Active Job can be installed with RubyGems:
102
+
103
+ ```
104
+ $ gem install activejob
105
+ ```
106
+
107
+ Source code can be downloaded as part of the \Rails project on GitHub:
108
+
109
+ * https://github.com/rails/rails/tree/main/activejob
110
+
111
+
112
+ ## License
113
+
114
+ Active Job is released under the MIT license:
115
+
116
+ * https://opensource.org/licenses/MIT
117
+
118
+
119
+ ## Support
120
+
121
+ API documentation is at:
122
+
123
+ * https://api.rubyonrails.org
124
+
125
+ Bug reports for the Ruby on \Rails project can be filed here:
126
+
127
+ * https://github.com/rails/rails/issues
128
+
129
+ Feature requests should be discussed on the rails-core mailing list here:
130
+
131
+ * https://discuss.rubyonrails.org/c/rubyonrails-core
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bigdecimal"
4
+ require "active_support/core_ext/hash"
5
+
6
+ module ActiveJob
7
+ # Raised when an exception is raised during job arguments deserialization.
8
+ #
9
+ # Wraps the original exception raised as +cause+.
10
+ class DeserializationError < StandardError
11
+ def initialize # :nodoc:
12
+ super("Error while trying to deserialize arguments: #{$!.message}")
13
+ set_backtrace $!.backtrace
14
+ end
15
+ end
16
+
17
+ # Raised when an unsupported argument type is set as a job argument. We
18
+ # currently support String, Integer, Float, NilClass, TrueClass, FalseClass,
19
+ # BigDecimal, Symbol, Date, Time, DateTime, ActiveSupport::TimeWithZone,
20
+ # ActiveSupport::Duration, Hash, ActiveSupport::HashWithIndifferentAccess,
21
+ # Array, Range, or GlobalID::Identification instances, although this can be
22
+ # extended by adding custom serializers.
23
+ # Raised if you set the key for a Hash something else than a string or
24
+ # a symbol. Also raised when trying to serialize an object which can't be
25
+ # identified with a GlobalID - such as an unpersisted Active Record model.
26
+ class SerializationError < ArgumentError; end
27
+
28
+ module Arguments
29
+ extend self
30
+ # Serializes a set of arguments. Intrinsic types that can safely be
31
+ # serialized without mutation are returned as-is. Arrays/Hashes are
32
+ # serialized element by element. All other types are serialized using
33
+ # GlobalID.
34
+ def serialize(arguments)
35
+ arguments.map { |argument| serialize_argument(argument) }
36
+ end
37
+
38
+ # Deserializes a set of arguments. Intrinsic types that can safely be
39
+ # deserialized without mutation are returned as-is. Arrays/Hashes are
40
+ # deserialized element by element. All other types are deserialized using
41
+ # GlobalID.
42
+ def deserialize(arguments)
43
+ arguments.map { |argument| deserialize_argument(argument) }
44
+ rescue
45
+ raise DeserializationError
46
+ end
47
+
48
+ private
49
+ # :nodoc:
50
+ GLOBALID_KEY = "_aj_globalid"
51
+ # :nodoc:
52
+ SYMBOL_KEYS_KEY = "_aj_symbol_keys"
53
+ # :nodoc:
54
+ RUBY2_KEYWORDS_KEY = "_aj_ruby2_keywords"
55
+ # :nodoc:
56
+ WITH_INDIFFERENT_ACCESS_KEY = "_aj_hash_with_indifferent_access"
57
+ # :nodoc:
58
+ OBJECT_SERIALIZER_KEY = "_aj_serialized"
59
+
60
+ # :nodoc:
61
+ RESERVED_KEYS = [
62
+ GLOBALID_KEY, GLOBALID_KEY.to_sym,
63
+ SYMBOL_KEYS_KEY, SYMBOL_KEYS_KEY.to_sym,
64
+ RUBY2_KEYWORDS_KEY, RUBY2_KEYWORDS_KEY.to_sym,
65
+ OBJECT_SERIALIZER_KEY, OBJECT_SERIALIZER_KEY.to_sym,
66
+ WITH_INDIFFERENT_ACCESS_KEY, WITH_INDIFFERENT_ACCESS_KEY.to_sym,
67
+ ]
68
+ private_constant :RESERVED_KEYS, :GLOBALID_KEY,
69
+ :SYMBOL_KEYS_KEY, :RUBY2_KEYWORDS_KEY, :WITH_INDIFFERENT_ACCESS_KEY
70
+
71
+ def serialize_argument(argument)
72
+ case argument
73
+ when nil, true, false, Integer, Float # Types that can hardly be subclassed
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
85
+ when GlobalID::Identification
86
+ convert_to_global_id_hash(argument)
87
+ when Array
88
+ argument.map { |arg| serialize_argument(arg) }
89
+ when ActiveSupport::HashWithIndifferentAccess
90
+ serialize_indifferent_hash(argument)
91
+ when Hash
92
+ symbol_keys = argument.each_key.grep(Symbol).map!(&:to_s)
93
+ aj_hash_key = if Hash.ruby2_keywords_hash?(argument)
94
+ RUBY2_KEYWORDS_KEY
95
+ else
96
+ SYMBOL_KEYS_KEY
97
+ end
98
+ result = serialize_hash(argument)
99
+ result[aj_hash_key] = symbol_keys
100
+ result
101
+ else
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
107
+ end
108
+ end
109
+
110
+ def deserialize_argument(argument)
111
+ case argument
112
+ when nil, true, false, String, Integer, Float
113
+ argument
114
+ when Array
115
+ argument.map { |arg| deserialize_argument(arg) }
116
+ when Hash
117
+ if serialized_global_id?(argument)
118
+ deserialize_global_id argument
119
+ elsif custom_serialized?(argument)
120
+ Serializers.deserialize(argument)
121
+ else
122
+ deserialize_hash(argument)
123
+ end
124
+ else
125
+ raise ArgumentError, "Can only deserialize primitive arguments: #{argument.inspect}"
126
+ end
127
+ end
128
+
129
+ def serialized_global_id?(hash)
130
+ hash.size == 1 && hash.include?(GLOBALID_KEY)
131
+ end
132
+
133
+ def deserialize_global_id(hash)
134
+ GlobalID::Locator.locate hash[GLOBALID_KEY]
135
+ end
136
+
137
+ def custom_serialized?(hash)
138
+ hash.key?(OBJECT_SERIALIZER_KEY)
139
+ end
140
+
141
+ def serialize_hash(argument)
142
+ argument.each_with_object({}) do |(key, value), hash|
143
+ hash[serialize_hash_key(key)] = serialize_argument(value)
144
+ end
145
+ end
146
+
147
+ def deserialize_hash(serialized_hash)
148
+ result = serialized_hash.transform_values { |v| deserialize_argument(v) }
149
+ if result.delete(WITH_INDIFFERENT_ACCESS_KEY)
150
+ result = result.with_indifferent_access
151
+ elsif symbol_keys = result.delete(SYMBOL_KEYS_KEY)
152
+ result = transform_symbol_keys(result, symbol_keys)
153
+ elsif symbol_keys = result.delete(RUBY2_KEYWORDS_KEY)
154
+ result = transform_symbol_keys(result, symbol_keys)
155
+ result = Hash.ruby2_keywords_hash(result)
156
+ end
157
+ result
158
+ end
159
+
160
+ def serialize_hash_key(key)
161
+ case key
162
+ when *RESERVED_KEYS
163
+ raise SerializationError.new("Can't serialize a Hash with reserved key #{key.inspect}")
164
+ when String, Symbol
165
+ key.to_s
166
+ else
167
+ raise SerializationError.new("Only string and symbol hash keys may be serialized as job arguments, but #{key.inspect} is a #{key.class}")
168
+ end
169
+ end
170
+
171
+ def serialize_indifferent_hash(indifferent_hash)
172
+ result = serialize_hash(indifferent_hash)
173
+ result[WITH_INDIFFERENT_ACCESS_KEY] = serialize_argument(true)
174
+ result
175
+ end
176
+
177
+ def transform_symbol_keys(hash, symbol_keys)
178
+ # NOTE: HashWithIndifferentAccess#transform_keys always
179
+ # returns stringified keys with indifferent access
180
+ # so we call #to_h here to ensure keys are symbolized.
181
+ hash.to_h.transform_keys do |key|
182
+ if symbol_keys.include?(key)
183
+ key.to_sym
184
+ else
185
+ key
186
+ end
187
+ end
188
+ end
189
+
190
+ def convert_to_global_id_hash(argument)
191
+ { GLOBALID_KEY => argument.to_global_id.to_s }
192
+ rescue URI::GID::MissingModelIdError
193
+ raise SerializationError, "Unable to serialize #{argument.class} " \
194
+ "without an id. (Maybe you forgot to call save?)"
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,79 @@
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/log_subscriber"
12
+ require "active_job/logging"
13
+ require "active_job/instrumentation"
14
+ require "active_job/timezones"
15
+ require "active_job/translation"
16
+
17
+ module ActiveJob # :nodoc:
18
+ # = Active Job \Base
19
+ #
20
+ # Active Job objects can be configured to work with different backend
21
+ # queuing frameworks. To specify a queue adapter to use:
22
+ #
23
+ # ActiveJob::Base.queue_adapter = :inline
24
+ #
25
+ # A list of supported adapters can be found in QueueAdapters.
26
+ #
27
+ # Active Job objects can be defined by creating a class that inherits
28
+ # from the ActiveJob::Base class. The only necessary method to
29
+ # implement is the "perform" method.
30
+ #
31
+ # To define an Active Job object:
32
+ #
33
+ # class ProcessPhotoJob < ActiveJob::Base
34
+ # def perform(photo)
35
+ # photo.watermark!('Rails')
36
+ # photo.rotate!(90.degrees)
37
+ # photo.resize_to_fit!(300, 300)
38
+ # photo.upload!
39
+ # end
40
+ # end
41
+ #
42
+ # Records that are passed in are serialized/deserialized using Global
43
+ # ID. More information can be found in Arguments.
44
+ #
45
+ # To enqueue a job to be performed as soon as the queuing system is free:
46
+ #
47
+ # ProcessPhotoJob.perform_later(photo)
48
+ #
49
+ # To enqueue a job to be processed at some point in the future:
50
+ #
51
+ # ProcessPhotoJob.set(wait_until: Date.tomorrow.noon).perform_later(photo)
52
+ #
53
+ # More information can be found in ActiveJob::Core::ClassMethods#set
54
+ #
55
+ # A job can also be processed immediately without sending to the queue:
56
+ #
57
+ # ProcessPhotoJob.perform_now(photo)
58
+ #
59
+ # == Exceptions
60
+ #
61
+ # * DeserializationError - Error class for deserialization errors.
62
+ # * SerializationError - Error class for serialization errors.
63
+ class Base
64
+ include Core
65
+ include QueueAdapter
66
+ include QueueName
67
+ include QueuePriority
68
+ include Enqueuing
69
+ include Execution
70
+ include Callbacks
71
+ include Exceptions
72
+ include Instrumentation
73
+ include Logging
74
+ include Timezones
75
+ include Translation
76
+
77
+ ActiveSupport.run_load_hooks(:active_job, self)
78
+ end
79
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/callbacks"
4
+ require "active_support/core_ext/module/attribute_accessors"
5
+
6
+ module ActiveJob
7
+ # = Active Job \Callbacks
8
+ #
9
+ # Active Job provides hooks during the life cycle of a job. Callbacks allow you
10
+ # to trigger logic during this cycle. Available callbacks are:
11
+ #
12
+ # * <tt>before_enqueue</tt>
13
+ # * <tt>around_enqueue</tt>
14
+ # * <tt>after_enqueue</tt>
15
+ # * <tt>before_perform</tt>
16
+ # * <tt>around_perform</tt>
17
+ # * <tt>after_perform</tt>
18
+ module Callbacks
19
+ extend ActiveSupport::Concern
20
+ include ActiveSupport::Callbacks
21
+
22
+ class << self
23
+ include ActiveSupport::Callbacks
24
+ define_callbacks :execute
25
+ end
26
+
27
+ included do
28
+ define_callbacks :perform, skip_after_callbacks_if_terminated: true
29
+ define_callbacks :enqueue, skip_after_callbacks_if_terminated: true
30
+ end
31
+
32
+ # These methods will be included into any Active Job object, adding
33
+ # callbacks for +perform+ and +enqueue+ methods.
34
+ module ClassMethods
35
+ # Defines a callback that will get called right before the
36
+ # job's perform method is executed.
37
+ #
38
+ # class VideoProcessJob < ActiveJob::Base
39
+ # queue_as :default
40
+ #
41
+ # before_perform do |job|
42
+ # UserMailer.notify_video_started_processing(job.arguments.first)
43
+ # end
44
+ #
45
+ # def perform(video_id)
46
+ # Video.find(video_id).process
47
+ # end
48
+ # end
49
+ #
50
+ def before_perform(*filters, &blk)
51
+ set_callback(:perform, :before, *filters, &blk)
52
+ end
53
+
54
+ # Defines a callback that will get called right after the
55
+ # job's perform method has finished.
56
+ #
57
+ # class VideoProcessJob < ActiveJob::Base
58
+ # queue_as :default
59
+ #
60
+ # after_perform do |job|
61
+ # UserMailer.notify_video_processed(job.arguments.first)
62
+ # end
63
+ #
64
+ # def perform(video_id)
65
+ # Video.find(video_id).process
66
+ # end
67
+ # end
68
+ #
69
+ def after_perform(*filters, &blk)
70
+ set_callback(:perform, :after, *filters, &blk)
71
+ end
72
+
73
+ # Defines a callback that will get called around the job's perform method.
74
+ #
75
+ # class VideoProcessJob < ActiveJob::Base
76
+ # queue_as :default
77
+ #
78
+ # around_perform do |job, block|
79
+ # UserMailer.notify_video_started_processing(job.arguments.first)
80
+ # block.call
81
+ # UserMailer.notify_video_processed(job.arguments.first)
82
+ # end
83
+ #
84
+ # def perform(video_id)
85
+ # Video.find(video_id).process
86
+ # end
87
+ # end
88
+ #
89
+ # You can access the return value of the job only if the execution wasn't halted.
90
+ #
91
+ # class VideoProcessJob < ActiveJob::Base
92
+ # around_perform do |job, block|
93
+ # value = block.call
94
+ # puts value # => "Hello World!"
95
+ # end
96
+ #
97
+ # def perform
98
+ # "Hello World!"
99
+ # end
100
+ # end
101
+ #
102
+ def around_perform(*filters, &blk)
103
+ set_callback(:perform, :around, *filters, &blk)
104
+ end
105
+
106
+ # Defines a callback that will get called right before the
107
+ # job is enqueued.
108
+ #
109
+ # class VideoProcessJob < ActiveJob::Base
110
+ # queue_as :default
111
+ #
112
+ # before_enqueue do |job|
113
+ # $statsd.increment "enqueue-video-job.try"
114
+ # end
115
+ #
116
+ # def perform(video_id)
117
+ # Video.find(video_id).process
118
+ # end
119
+ # end
120
+ #
121
+ def before_enqueue(*filters, &blk)
122
+ set_callback(:enqueue, :before, *filters, &blk)
123
+ end
124
+
125
+ # Defines a callback that will get called right after the
126
+ # job is enqueued.
127
+ #
128
+ # class VideoProcessJob < ActiveJob::Base
129
+ # queue_as :default
130
+ #
131
+ # after_enqueue do |job|
132
+ # result = job.successfully_enqueued? ? "success" : "failure"
133
+ # $statsd.increment "enqueue-video-job.#{result}"
134
+ # end
135
+ #
136
+ # def perform(video_id)
137
+ # Video.find(video_id).process
138
+ # end
139
+ # end
140
+ #
141
+ def after_enqueue(*filters, &blk)
142
+ set_callback(:enqueue, :after, *filters, &blk)
143
+ end
144
+
145
+ # Defines a callback that will get called around the enqueuing
146
+ # of the job.
147
+ #
148
+ # class VideoProcessJob < ActiveJob::Base
149
+ # queue_as :default
150
+ #
151
+ # around_enqueue do |job, block|
152
+ # $statsd.time "video-job.process" do
153
+ # block.call
154
+ # end
155
+ # end
156
+ #
157
+ # def perform(video_id)
158
+ # Video.find(video_id).process
159
+ # end
160
+ # end
161
+ #
162
+ def around_enqueue(*filters, &blk)
163
+ set_callback(:enqueue, :around, *filters, &blk)
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ class ConfiguredJob # :nodoc:
5
+ def initialize(job_class, options = {})
6
+ @options = options
7
+ @job_class = job_class
8
+ end
9
+
10
+ def perform_now(...)
11
+ @job_class.new(...).set(@options).perform_now
12
+ end
13
+
14
+ def perform_later(...)
15
+ @job_class.new(...).enqueue @options
16
+ end
17
+
18
+ def perform_all_later(multi_args)
19
+ @job_class.perform_all_later(multi_args, options: @options)
20
+ end
21
+ end
22
+ end