postburner 0.6.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7712222bcad943495a38f620aefaffbcc26d3483e68c07c1aae5102d20144baf
4
- data.tar.gz: 1dc644fcdb72b196e2694c2dd935b4f08cf3229873c08625a4db898e0195e7a3
3
+ metadata.gz: 9d8b5fb47d69c141d348c00520ff51579fc67f8300ac804f75b96cb023a8c584
4
+ data.tar.gz: 49d79bc8e8e04edc9cca6d74e5f66326573a8defc859fc54d875c02dee626e4b
5
5
  SHA512:
6
- metadata.gz: ea6308f6a9a13134ca84a693a933818d82d3ccf05a02f7f1bfc51a8d37178419143e9903e2f0b9a529dc3cab283196122dc6be833d0eeee10ec0a1ea3b5a9889
7
- data.tar.gz: 1b8ac590e3289de30eccfe3ef6a4d65fa0e034d6f43069b03e1190b324dab38dc65d5eb358e3ea306daa15db044a86151e3118a27b803cee2d78bfbfbd99facc
6
+ metadata.gz: 9f835395176f8ce70a2790e2e6f34e08ae051fde7711bd2ed17f83f2f211133dc15ba914967e5cf0737ab57b4e1737ea055cbb283ff4223f76921ad1dd2aea29
7
+ data.tar.gz: a793a67476072574c1f5e1a2439d21377ea2074053a3ef6834daac4c28fe9e72048e0d6333c1536dce4dcf8801ea449d8f506dd3e76c0d2af8631c21b94b304b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.7.0 - 2022-10-24
4
+
5
+ ### Added
6
+ - - add ActiveJob style callbacks for enqueue, attempt, processing, and processed.
7
+
8
+ ### Fixed
9
+ - remove assets config as for rails >=7
10
+
3
11
  ## v0.6.5 - 2022-05-21
4
12
 
5
13
  ### Fixed
@@ -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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Postburner
2
4
  # Must implement a perform method, if an exception is raised the job
3
5
  # doesn't complete.
@@ -14,6 +16,7 @@ module Postburner
14
16
  #
15
17
  class Job < ApplicationRecord
16
18
  include Backburner::Queue
19
+ include Callbacks
17
20
 
18
21
  LOG_LEVELS = [
19
22
  :debug,
@@ -48,7 +51,9 @@ module Postburner
48
51
 
49
52
  @_insert_options = options
50
53
 
51
- self.save!
54
+ run_callbacks :enqueue do
55
+ self.save!
56
+ end
52
57
  end
53
58
 
54
59
  def requeue!(options={})
@@ -73,77 +78,85 @@ module Postburner
73
78
  [Postburner::Job] [#{id}] Not Found.
74
79
  MSG
75
80
  end
76
- job&.perform!(job.args)
81
+ #job&.perform!(job.args)
82
+ job.perform!(job.args)
77
83
  end
78
84
 
79
85
  def perform!(args={})
80
- self.attempting
81
-
82
- self.update_columns(
83
- attempting_at: self.attempting_at,
84
- attempts: self.attempts,
85
- attempt_count: self.attempts.length,
86
- lag: self.lag,
87
- processing_at: Time.zone.now,
88
- )
89
-
90
- begin
91
- if self.queued_at.nil?
92
- self.log! "Not Queued", level: :error
93
- return
94
- end
95
-
96
- if self.queued_at > Time.zone.now
97
- self.log! "Future Queued", level: :error
98
- return
99
- end
100
-
101
- if self.processed_at.present?
102
- self.log! "Already Processed", level: :error
103
- self.delete!
104
- return
105
- end
106
-
107
- if self.removed_at.present?
108
- self.log! "Removed", level: :error
109
- return
110
- end
111
-
112
- if self.run_at && self.run_at > Time.zone.now
113
- response = self.insert! delay: self.run_at - Time.zone.now
114
- self.log! "PREMATURE; RE-INSERTED: #{response}"
115
- return
116
- end
117
-
118
- self.log!("START (bkid #{self.bkid})")
86
+ run_callbacks :attempt do
87
+ self.attempting
88
+
89
+ self.update_columns(
90
+ attempting_at: self.attempting_at,
91
+ attempts: self.attempts,
92
+ attempt_count: self.attempts.length,
93
+ lag: self.lag,
94
+ processing_at: Time.zone.now,
95
+ )
119
96
 
120
97
  begin
121
- self.perform(args)
98
+ if self.queued_at.nil?
99
+ self.log! "Not Queued", level: :error
100
+ return
101
+ end
102
+
103
+ if self.queued_at > Time.zone.now
104
+ self.log! "Future Queued", level: :error
105
+ return
106
+ end
107
+
108
+ if self.processed_at.present?
109
+ self.log! "Already Processed", level: :error
110
+ self.delete!
111
+ return
112
+ end
113
+
114
+ if self.removed_at.present?
115
+ self.log! "Removed", level: :error
116
+ return
117
+ end
118
+
119
+ if self.run_at && self.run_at > Time.zone.now
120
+ response = self.insert! delay: self.run_at - Time.zone.now
121
+ self.log! "PREMATURE; RE-INSERTED: #{response}"
122
+ return
123
+ end
124
+
125
+ self.log!("START (bkid #{self.bkid})")
126
+
127
+ run_callbacks :processing do
128
+ begin
129
+ self.perform(args)
130
+ rescue Exception => exception
131
+ self.persist_metadata!
132
+ self.log! '[Postburner] Exception raised during perform prevented completion.'
133
+ raise exception
134
+ end
135
+ end
136
+
137
+ self.log!("DONE (bkid #{self.bkid})")
138
+
139
+ begin
140
+ now = Time.zone.now
141
+ _duration = (now - self.processing_at) * 1000 rescue nil
142
+
143
+ run_callbacks :processed do
144
+ persist_metadata!(
145
+ processed_at: now,
146
+ duration: _duration,
147
+ )
148
+ end
149
+ rescue Exception => e
150
+ self.log_exception!(e)
151
+ self.log! '[Postburner] Could not set data after processing.'
152
+ # TODO README doesn't retry if Postburner is to blame
153
+ end
154
+
122
155
  rescue Exception => exception
123
- self.persist_metadata!
124
- self.log! '[Postburner] Exception raised during perform prevented completion.'
156
+ self.log_exception!(exception)
125
157
  raise exception
126
158
  end
127
-
128
- self.log!("DONE (bkid #{self.bkid})")
129
-
130
- begin
131
- now = Time.zone.now
132
- _duration = (now - self.processing_at) * 1000 rescue nil
133
- persist_metadata!(
134
- processed_at: now,
135
- duration: _duration,
136
- )
137
- rescue Exception => e
138
- self.log_exception!(e)
139
- self.log! '[Postburner] Could not set data after processing.'
140
- # TODO README doesn't retry if Postburner is to blame
141
- end
142
-
143
- rescue Exception => exception
144
- self.log_exception!(exception)
145
- raise exception
146
- end
159
+ end # run_callbacks :attempt
147
160
 
148
161
  end
149
162
 
@@ -1,3 +1,3 @@
1
1
  module Postburner
2
- VERSION = '0.6.5'
2
+ VERSION = '0.7.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: postburner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.5
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Smith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-21 00:00:00.000000000 Z
11
+ date: 2022-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -79,6 +79,7 @@ files:
79
79
  - Rakefile
80
80
  - app/assets/config/postburner_manifest.js
81
81
  - app/assets/stylesheets/postburner/application.css
82
+ - app/concerns/postburner/callbacks.rb
82
83
  - app/controllers/postburner/application_controller.rb
83
84
  - app/controllers/postburner/jobs_controller.rb
84
85
  - app/controllers/postburner/static_controller.rb
@@ -122,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
123
  - !ruby/object:Gem::Version
123
124
  version: '0'
124
125
  requirements: []
125
- rubygems_version: 3.1.6
126
+ rubygems_version: 3.3.7
126
127
  signing_key:
127
128
  specification_version: 4
128
129
  summary: Postgres backed beanstalkd queue via backburner