postburner 0.7.2 → 0.9.0.rc.1

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.
@@ -0,0 +1,286 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/callbacks"
4
+ require "active_support/core_ext/object/with_options"
5
+ require "active_support/core_ext/module/attribute_accessors"
6
+
7
+ module Postburner
8
+ # = Postburner Job Callbacks
9
+ #
10
+ # Postburner Job provides hooks during the life cycle of a job. Callbacks allow you
11
+ # to trigger logic during this cycle. In called order, available callbacks are:
12
+ #
13
+ # * <tt>before_enqueue</tt>
14
+ # * <tt>after_enqueue</tt>
15
+ # * <tt>before_attempt</tt>
16
+ # * <tt>before_processing</tt>
17
+ # * <tt>after_processing</tt>
18
+ # * <tt>after_processed</tt>
19
+ # * <tt>after_attempt</tt>
20
+ #
21
+ # Around callbacks are also defined:
22
+ # * <tt>around_enqueue</tt>
23
+ # * <tt>around_attempt</tt>
24
+ # * <tt>around_processing</tt>
25
+ #
26
+ # NOTE: Calling the same callback multiple times will overwrite previous callback definitions.
27
+ #
28
+ module Callbacks
29
+ extend ActiveSupport::Concern
30
+ include ActiveSupport::Callbacks
31
+
32
+ included do
33
+ cattr_accessor :skip_after_callbacks_if_terminated,
34
+ instance_accessor: false,
35
+ default: false
36
+
37
+ with_options(skip_after_callbacks_if_terminated: skip_after_callbacks_if_terminated) do
38
+ define_callbacks :enqueue
39
+ define_callbacks :attempt
40
+ define_callbacks :processing
41
+ define_callbacks :processed
42
+ end
43
+ end
44
+ module ClassMethods
45
+ def inherited(klass)
46
+ klass.get_callbacks(:enqueue).
47
+ config[:skip_after_callbacks_if_terminated] =
48
+ skip_after_callbacks_if_terminated
49
+ klass.get_callbacks(:processing).
50
+ config[:skip_after_callbacks_if_terminated] =
51
+ skip_after_callbacks_if_terminated
52
+ klass.get_callbacks(:attempt).
53
+ config[:skip_after_callbacks_if_terminated] =
54
+ skip_after_callbacks_if_terminated
55
+ klass.get_callbacks(:processed).
56
+ config[:skip_after_callbacks_if_terminated] =
57
+ skip_after_callbacks_if_terminated
58
+ super
59
+ end
60
+
61
+ # Defines a callback that will get called right before the
62
+ # job starts and any metadata is persisted.
63
+ #
64
+ # class VideoProcessJob < Postburner::Base
65
+ #
66
+ # before_attempt do |job|
67
+ # $statsd.increment "attempting-video-job.try"
68
+ # end
69
+ #
70
+ # def perform(video_id)
71
+ # Video.find(video_id).process
72
+ # end
73
+ # end
74
+ #
75
+ def before_attempt(*filters, &blk)
76
+ set_callback(:attempt, :before, *filters, &blk)
77
+ end
78
+
79
+ # Defines a callback that will get called right after the
80
+ # job finishes and all metadata is persisted.
81
+ #
82
+ # This isn't called unless the attempt finishes without error,
83
+ # though this is subject to change in the future
84
+ #
85
+ # class VideoProcessJob < Postburner::Base
86
+ #
87
+ # before_attempt do |job|
88
+ # $statsd.increment "attempt-complete-video-job.try"
89
+ # end
90
+ #
91
+ # def perform(video_id)
92
+ # Video.find(video_id).process
93
+ # end
94
+ # end
95
+ #
96
+ def after_attempt(*filters, &blk)
97
+ set_callback(:attempt, :after, *filters, &blk)
98
+ end
99
+
100
+ # Defines a callback that will get called around the attempt
101
+ # of the job.
102
+ #
103
+ # class VideoProcessJob < Postburner::Base
104
+ #
105
+ # around_enqueue do |job, block|
106
+ # $statsd.time "video-job.process" do
107
+ # block.call
108
+ # end
109
+ # end
110
+ #
111
+ # def perform(video_id)
112
+ # Video.find(video_id).process
113
+ # end
114
+ # end
115
+ #
116
+ def around_attempt(*filters, &blk)
117
+ set_callback(:attempt, :around, *filters, &blk)
118
+ end
119
+
120
+ # Defines a callback that will get called right before the
121
+ # job's perform method is executed.
122
+ #
123
+ # class VideoProcessJob < Postburner::Base
124
+ #
125
+ # before_processing do |job|
126
+ # UserMailer.notify_video_started_processing(job.arguments.first)
127
+ # end
128
+ #
129
+ # def perform(video_id)
130
+ # Video.find(video_id).process
131
+ # end
132
+ # end
133
+ #
134
+ def before_processing(*filters, &blk)
135
+ set_callback(:processing, :before, *filters, &blk)
136
+ end
137
+
138
+ # Defines a callback that will get called right after the
139
+ # job's perform method has finished.
140
+ #
141
+ # class VideoProcessJob < Postburner::Base
142
+ #
143
+ # after_processing do |job|
144
+ # UserMailer.notify_video_processed(job.arguments.first)
145
+ # end
146
+ #
147
+ # def perform(video_id)
148
+ # Video.find(video_id).process
149
+ # end
150
+ # end
151
+ #
152
+ def after_processing(*filters, &blk)
153
+ set_callback(:processing, :after, *filters, &blk)
154
+ end
155
+
156
+ # Defines a callback that will get called around the job's perform method.
157
+ #
158
+ # class VideoProcessJob < Postburner::Base
159
+ #
160
+ # around_processing do |job, block|
161
+ # UserMailer.notify_video_started_processing(job.arguments.first)
162
+ # block.call
163
+ # UserMailer.notify_video_processed(job.arguments.first)
164
+ # end
165
+ #
166
+ # def perform(video_id)
167
+ # Video.find(video_id).process
168
+ # end
169
+ # end
170
+ #
171
+ # You can access the return value of the job only if the execution wasn't halted.
172
+ #
173
+ # class VideoProcessJob < Postburner::Base
174
+ # around_processing do |job, block|
175
+ # value = block.call
176
+ # puts value # => "Hello World!"
177
+ # end
178
+ #
179
+ # def perform
180
+ # "Hello World!"
181
+ # end
182
+ # end
183
+ #
184
+ def around_processing(*filters, &blk)
185
+ set_callback(:processing, :around, *filters, &blk)
186
+ end
187
+
188
+ # Defines a callback that will get called right after the
189
+ # job's processed_at timestamp has been persisted, marking the
190
+ # job as successfully completed, i.e. no errors raised.
191
+ #
192
+ # This is rather similar to after_processing but all of the
193
+ # job's metadata has been set.
194
+ #
195
+ # class VideoProcessJob < Postburner::Base
196
+ #
197
+ # after_processed do |job|
198
+ # UserMailer.notify_video_processed(job.arguments.first)
199
+ # end
200
+ #
201
+ # def perform(video_id)
202
+ # Video.find(video_id).process
203
+ # end
204
+ # end
205
+ #
206
+ def after_processed(*filters, &blk)
207
+ set_callback(:processed, :after, *filters, &blk)
208
+ end
209
+
210
+ # Defines a callback that will get called right before the
211
+ # job is enqueued.
212
+ #
213
+ # class VideoProcessJob < Postburner::Base
214
+ #
215
+ # before_enqueue do |job|
216
+ # $statsd.increment "enqueue-video-job.try"
217
+ # end
218
+ #
219
+ # def perform(video_id)
220
+ # Video.find(video_id).process
221
+ # end
222
+ # end
223
+ #
224
+ def before_enqueue(*filters, &blk)
225
+ set_callback(:enqueue, :before, *filters, &blk)
226
+ end
227
+
228
+ # Defines a callback that will get called right after the
229
+ # job is enqueued.
230
+ #
231
+ # class VideoProcessJob < Postburner::Base
232
+ #
233
+ # after_enqueue do |job|
234
+ # $statsd.increment "enqueue-video-job.success"
235
+ # end
236
+ #
237
+ # def perform(video_id)
238
+ # Video.find(video_id).process
239
+ # end
240
+ # end
241
+ #
242
+ def after_enqueue(*filters, &blk)
243
+ set_callback(:enqueue, :after, *filters, &blk)
244
+ end
245
+
246
+ # Defines a callback that will get called around the enqueuing
247
+ # of the job.
248
+ #
249
+ # class VideoProcessJob < Postburner::Base
250
+ #
251
+ # around_enqueue do |job, block|
252
+ # $statsd.time "video-job.process" do
253
+ # block.call
254
+ # end
255
+ # end
256
+ #
257
+ # def perform(video_id)
258
+ # Video.find(video_id).process
259
+ # end
260
+ # end
261
+ #
262
+ def around_enqueue(*filters, &blk)
263
+ set_callback(:enqueue, :around, *filters, &blk)
264
+ end
265
+ end
266
+
267
+ private
268
+
269
+ # NOTE processed / attempt exclueded here -- intentionally
270
+ #
271
+ def halted_callback_hook(_filter, name) # :nodoc:
272
+ return super unless %i(enqueue processing).include?(name.to_sym)
273
+ callbacks = public_send("_#{name}_callbacks")
274
+
275
+ if !self.class.skip_after_callbacks_if_terminated && callbacks.any? { |c| c.kind == :after }
276
+ ActiveSupport::Deprecation.warn(<<~EOM)
277
+ In Rails 7.0, `after_enqueue`/`after_work` callbacks no longer run if `before_enqueue`/`before_work` respectively halts with `throw :abort`.
278
+ To enable this behavior, uncomment the `config.active_job.skip_after_callbacks_if_terminated` config
279
+ in the new 6.1 framework defaults initializer.
280
+ EOM
281
+ end
282
+
283
+ super
284
+ end
285
+ end
286
+ end