postburner 0.3.2 → 0.6.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: ba4b7b0b6ccdc3f0ce25453614c73e683dcac10fde47c6382337e9d0a8eecc42
4
- data.tar.gz: 20899869073130b8fb856009c1a69dfa5b0bc4594c79477ff7593d17775cf35f
3
+ metadata.gz: f0c2a65b18596dafa8809d07924e2274f7adc05ce971fea1b82143c7132f2929
4
+ data.tar.gz: e3000b8fa490aec4fb1c8b49c54fe7ee78613b3e7e3849c2270d7a7dd01adecd
5
5
  SHA512:
6
- metadata.gz: 32d316908465caab8c6276ba6db4be43bfdcab5185146cbff59a708057ef331dac90374b817f65a25c623530cfbcb8bfbded3d152aaabd7607fd8df4e7288a1a
7
- data.tar.gz: b7ba8bce12c6ddd9e2e353b8dd11fb6e87cd7e7ecbde3a410bc73e8c06464cfb6142172200528e66a2cdd3e02f903366f27ebd7d63e0b2ca14fb6a83335269bd
6
+ metadata.gz: 87cb7aec3924346ab43b93f5886aebfb1b138a36b199eb3e10032404a23b07774c287cb96ed8c4889feabde1106aba63d23d6429cead43f3eec8211f257d6baa
7
+ data.tar.gz: 94e32291c4f00db869a630adeea7e44abb92c4938e2314fc5e46ea487b874acc4a74b80771bd8db8944f3a7c98e06101ef90a36f8da5bf72d7fecc82fbd14c3c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.6.0 - 2021-11-01
4
+
5
+ ### Added
6
+ - update exception handling to better show where the error was raised.
7
+ - update logging to match errata format.
8
+ - update documentation.
9
+
10
+ ## v0.5.0 - 2021-10-27
11
+
12
+ ### Added
13
+ - add mailer, action, params accessors to Mailer for easy access in subclassed jobs.
14
+ - add logging to Mailer perform.
15
+ - add save to #queue! job if unsaved
16
+ - add block with logging if queued_at isn't set or isn't prior to run time.
17
+
18
+ ## v0.4.0 - 2021-10-12
19
+
20
+ ### Added
21
+ - Change Job logging to persisted in perform.
22
+ - Update mailer job to use #with and support serializations.
23
+
24
+ ## v0.3.3 - 2021-06-15
25
+
26
+ ### Fixed
27
+ - re-raise exception after logging during perform.
28
+ - log but swallow post perform data update exceptions.
29
+ - only allow remove! if job still present.
30
+
31
+ ### Added
32
+ - Job#log! and Job#log_exception! that save the data immediately.
33
+
3
34
  ## v0.3.2 - 2021-05-07
4
35
 
5
36
  ### Fixed
data/README.md CHANGED
@@ -1,29 +1,15 @@
1
1
  # Postburner
2
- An ActiveRecord layer on top of Backburner for inspecting and auditing the
3
- queue, especially for delayed jobs. It isn't meant to be fast, but safe.
2
+ An ActiveRecord layer on top of [Backburner](https://github.com/nesquena/backburner) for inspecting and auditing the
3
+ queue, especially for delayed jobs. It isn't meant to be outperform other queues, but be safe (and inspectable).
4
4
 
5
- It is meant to be complementary to Backburner. Use Backburner as the default
5
+ It is meant to be complementary to [Backburner](https://github.com/nesquena/backburner). Use Backburner as the default
6
6
  ActiveJob processor for mailers, active storage, and the like. Use a
7
- `Postburner::Job` for things that you want to track.
7
+ `Postburner::Job` for things that you want to track. See [Comparison to Backburner](#comparison-to-backburner) for more.
8
8
 
9
- Comes with a mountable interface that can be password protected with whatever
10
- authentication you use in your project.
11
-
12
- Also meant to be a replacement/upgrade for [Que](https://github.com/que-rb/que).
13
- If you need something faster, but backed with ACID compliance, check out Que.
14
- There are some additional features in Postburner such as retained jobs
15
- after processing, stats, per job logging, etc.
16
-
17
- Compared to plain [Backburner](https://github.com/nesquena/backburner),
18
- Postburner adds:
19
- - Database Jobs for inspection, linking, auditing, removal (and deletion)
20
- - Direct access to associated [Beanstalk](https://beanstalkd.github.io/) (via [beaneater](https://github.com/beanstalkd/beaneater))
21
- - Job Statistics (lag, attempts, logs, tracked errors)
22
- - Convenience methods to clear tubes, stats, and connections for Beanstalk.
23
-
24
- Otherwise, Postburner tries to be a super simple layer on `Backburner::Queue`
25
- and `ActiveRecord`. Every tool with either of those are avilabel in
26
- `Postburner::Job`s.
9
+ Postburner meant to be a replacement/upgrade for [Que](https://github.com/que-rb/que).
10
+ If you need something faster, check out Que - we love it! Postburner is built for a slightly different purpose: to be
11
+ simple, safe, and inspectable. All of which Que has (or can be added), but are included by default with some architecture
12
+ differences. See [Comparison to Que](#comparison-to-que) for more.
27
13
 
28
14
  ## Usage
29
15
 
@@ -33,51 +19,251 @@ class RunDonation < Postburner::Job
33
19
  queue_priority 0 # 0 is highest priority
34
20
  queue_max_job_retries 0 # don't retry
35
21
 
36
- def process(args)
22
+ def perform(args)
37
23
  # do long tasks here
38
24
  # also have access to self.args
39
25
  end
40
26
  end
41
27
 
42
- RunDonation.create!(args: {donation_id: 123}).queue!
28
+ # RunDonation#create! is the `ActiveRecord` method, so it returns a model,
29
+ # you can manipulate, add columns to the table to, reference with foreign
30
+ # keys, etc.
31
+ job = RunDonation.create!(args: {donation_id: 123})
32
+ # NOTE Make sure use use an after_commit or after_save_commit, etc to avoid
33
+ # any race conditions of Postburner trying to process before a required
34
+ # database mutation is commited.
35
+ job.queue!
43
36
  => {:status=>"INSERTED", :id=>"1139"}
37
+
38
+ # queue for later with `:at`
44
39
  RunDonation.create!(args: {donation_id: 123}).queue! at: Time.zone.now + 2.days
45
40
  => {:status=>"INSERTED", :id=>"1140"}
46
41
 
47
- # `delay` takes priority over `at`
42
+ # queue for later with `:delay`
43
+ #
44
+ # `:delay` takes priority over `:at`takes priority over `:at` because the
45
+ # beanstalkd protocol uses uses `delay`
48
46
  RunDonation.create!(args: {donation_id: 123}).queue! delay: 1.hour
49
47
  => {:status=>"INSERTED", :id=>"1141"}
50
48
  ```
51
49
 
50
+ ### Mailers
51
+
52
+ ```ruby
53
+ j = Postburner::Mailer.
54
+ delivery(UserMailer, :welcome)
55
+ .with(name: 'Freddy')
56
+
57
+ j.queue!
58
+ => {:status=>"INSERTED", :id=>"1139"}
59
+ ```
60
+
61
+ ### [Beaneater](https://github.com/beanstalkd/beaneater) and [beanstalkd](https://raw.githubusercontent.com/beanstalkd/beanstalkd/master/doc/protocol.txt) attributes and methods
62
+ ```ruby
63
+ # get the beanstalkd job id
64
+ job.bkid
65
+ => 1104
66
+
67
+ # get the beaneater job, call any beaneater methods on this object
68
+ job.beanstalk_job
69
+
70
+ # get the beanstald stats
71
+ job.beanstalk_job.stats
72
+
73
+ # kick the beanstalk job
74
+ job.kick!
75
+
76
+ # delete beankstalkd job, retain the job model
77
+ job.delete!
78
+
79
+ # delete beankstalkd job, retain the job model, but set `removed_at` on model.
80
+ job.remove!
81
+
82
+ # or simply remove the model, which will clean up the beanstalkd job in a before_destroy hook
83
+ job.destroy # OR job.destroy!
84
+
85
+ # get a cached Backburner connection and inspect it (or even use it directly)
86
+ c = Postburner.connection
87
+ c.beanstalk.tubes.to_a
88
+ c.beanstalk.tubes.to_a.map{|t| c.tubes[t.name].peek(:buried)}
89
+ c.beanstalk.tubes['ss.development.caching'].stats
90
+ c.beanstalk.tubes['ss.development.caching'].peek(:buried).kick
91
+ c.beanstalk.tubes['ss.development.caching'].kick(3)
92
+ c.close
93
+
94
+ # automatically close
95
+ Postburner.connected do |connection|
96
+ # do stuff with connection
97
+ end
98
+ ```
99
+
100
+ Read about the [beanstalkd protocol](https://raw.githubusercontent.com/beanstalkd/beanstalkd/master/doc/protocol.txt).
101
+
102
+ ### Basic model fields
103
+ ```ruby
104
+ # ActiveRecord primary key
105
+ job.id
106
+
107
+ # int id of the beankstalkd job
108
+ job.bkid
109
+
110
+ # string uuid
111
+ job.sid
112
+
113
+ # ActiveRecord STI job subtype
114
+ job.type
115
+
116
+ # jsonb arguments for use in job
117
+ job.args
118
+
119
+ # time job should run - not intended to be changed
120
+ # TODO run_at should be readonly after create
121
+ job.run_at
122
+ ```
123
+
124
+ ### Job statistics
125
+ ```ruby
126
+ # when job was inserted into beankstalkd
127
+ job.queued_at
128
+
129
+ # last time attempted
130
+ job.attempting_at
131
+
132
+ # last time processing started
133
+ job.processing_at
134
+
135
+ # when completed
136
+ job.processed_at
137
+
138
+ # when removed, may be nil
139
+ job.removed_at
140
+
141
+ # lag in ms from run_at/queued_at to attempting_at
142
+ job.lag
143
+
144
+ # duration of processing in ms
145
+ job.duration
146
+
147
+ # number of attempts
148
+ job.attempt_count
149
+
150
+ # number of errors (length of errata)
151
+ job.error_count
152
+
153
+ # number of log entries (length of logs)
154
+ job.log_count
155
+
156
+ # array of attempting_at times
157
+ job.attempts
158
+
159
+ # array of errors
160
+ job.errata
161
+
162
+ # array of log messages
163
+ job.logs
164
+ ```
165
+
166
+ ### Job logging and exceptions
167
+
168
+ Optionally, you can:
169
+ 1. Add log messages to the job during processing to `logs`
170
+ 1. Add log your own exceptions to `errata`
171
+
172
+ ```ruby
173
+ class RunDonation < Postburner::Job
174
+ queue 'critical'
175
+ queue_priority 0 # 0 is highest priority
176
+ queue_max_job_retries 0 # don't retry
177
+
178
+ def perform(args)
179
+ # log at task, defaults to `:info`, but `:debug`, `:warning`, `:error`
180
+ log "Log bad condition...", level: :error
181
+
182
+ begin
183
+ # danger
184
+ rescue Exception => e
185
+ log_exception e
186
+ end
187
+ end
188
+ end
189
+ ```
190
+
191
+ ### Optionally, mount the engine
192
+
193
+ ```ruby
194
+ mount Postburner::Engine => "/postburner"
195
+
196
+ # mount only for development inspection
197
+ mount Postburner::Engine => "/postburner" if Rails.env.development?
198
+ ```
199
+
200
+ [Open the controller](https://guides.rubyonrails.org/engines.html#overriding-models-and-controllers)
201
+ to add your own authentication or changes - or just create your own routes, controllers, and views.
202
+
203
+ [Override the views](https://guides.rubyonrails.org/engines.html#overriding-views) to make them
204
+ prettier - or follow the suggestion above and use your own.
205
+
52
206
  ## Installation
53
207
 
208
+ First [install beanstalkd](https://beanstalkd.github.io/download.html). On Debian-based systems, that goes like this:
209
+ ```bash
210
+ sudo apt-get install beanstalkd
211
+ ```
212
+
213
+ Then add to your Gemfile.
54
214
  ```ruby
55
- # in Gemfile
56
215
  gem 'postburner'
57
216
  ```
58
217
 
218
+ Install...
59
219
  ```bash
60
220
  $ bundle
221
+ ```
61
222
 
223
+ After bundling, install the migration.
224
+ ```
62
225
  # install migration, possible to edit and add attributes or indexes as needed.
63
226
  $ bundle exec rails g postburner:install
64
227
  ```
65
228
 
66
- Add a `config/initializers/backburner.rb` with option found [here](https://github.com/nesquena/backburner#configuration).
229
+ Inspect `XXX_create_postburner_jobs.rb`. (The template is [here](-/blob/master/lib/generators/postburner/install/templates/migrations/create_postburner_jobs.rb.erb)).The required attributes are in there, but add more if you would like to use them,
230
+ or do it in a separate migration. By default, several indexes are added
67
231
 
68
- Set `Backburner` for `ActiveJob`
232
+ Because `Postburner` is built on `Backburner`, add a `config/initializers/backburner.rb` with option found [here](https://github.com/nesquena/backburner#configuration).
233
+ ```ruby
234
+ Backburner.configure do |config|
235
+ config.beanstalk_url = "beanstalk://127.0.0.1"
236
+ config.tube_namespace = "some.app.production"
237
+ config.namespace_separator = "."
238
+ config.on_error = lambda { |e| puts e }
239
+ config.max_job_retries = 3 # default 0 retries
240
+ config.retry_delay = 2 # default 5 seconds
241
+ config.retry_delay_proc = lambda { |min_retry_delay, num_retries| min_retry_delay + (num_retries ** 3) }
242
+ config.default_priority = 65536
243
+ config.respond_timeout = 120
244
+ config.default_worker = Backburner::Workers::Simple
245
+ config.logger = Logger.new(STDOUT)
246
+ config.primary_queue = "backburner-jobs"
247
+ config.priority_labels = { :custom => 50, :useless => 1000 }
248
+ config.reserve_timeout = nil
249
+ config.job_serializer_proc = lambda { |body| JSON.dump(body) }
250
+ config.job_parser_proc = lambda { |body| JSON.parse(body) }
251
+ end
252
+ ```
253
+
254
+ Finally, set `Backburner` for `ActiveJob`
69
255
  ```
70
256
  # config/application.rb
71
257
  config.active_job.queue_adapter = :backburner
72
258
  ```
73
259
 
74
260
  Postburner may later provide an adapter, but we recommend using `Postburner::Job` classes
75
- directyly.
261
+ directly.
76
262
 
77
263
  Add jobs to `app/jobs/`. There currently is no generator.
264
+
78
265
  ```ruby
79
266
  # app/jobs/run_donation.rb
80
-
81
267
  class RunDonation < Postburner::Job
82
268
  queue 'critical'
83
269
  queue_priority 0 # 0 is highest priority
@@ -88,6 +274,34 @@ class RunDonation < Postburner::Job
88
274
  # also have access to self.args
89
275
  end
90
276
  end
277
+ ```
278
+
279
+ ### Comparison to Backburner
280
+
281
+ Compared to plain [Backburner](https://github.com/nesquena/backburner),
282
+ Postburner adds:
283
+ - Database Jobs for inspection, linking, auditing, removal (and deletion)
284
+ - Direct access to associated [Beanstalk](https://beanstalkd.github.io/) (via [beaneater](https://github.com/beanstalkd/beaneater))
285
+ - Job Statistics (lag, attempts, logs, tracked errors)
286
+ - Convenience methods to clear tubes, stats, and connections for Beanstalk.
287
+
288
+ Otherwise, Postburner tries to be a super simple layer on `Backburner::Queue`
289
+ and `ActiveRecord`. Every tool with either of those are available in
290
+ `Postburner::Job`s.
291
+
292
+ Comes with a mountable interface that can be password protected with whatever
293
+ authentication you use in your project.
294
+
295
+ ### Comparison to Que
296
+
297
+ Postburner meant to be a replacement/upgrade for [Que](https://github.com/que-rb/que).
298
+ However, if you need something faster and backed with ACID compliance, check out Que.
299
+
300
+ Postburner has some additional features such as retained jobs after processing,
301
+ stats, per job logging, etc.
302
+
303
+ Postburner is meant to be simpler than `Que`. Que is incredible, but jobs should
304
+ be simple so the logic and history can be transparent.
91
305
 
92
306
  ## Contributing
93
307
  Submit a pull request. Follow conventions of the project. Be nice.
@@ -102,7 +316,6 @@ Submit a pull request. Follow conventions of the project. Be nice.
102
316
  - Job generator
103
317
  - Build file in app/jobs
104
318
  - Inherit from Postburner::Job
105
- - Job generator
106
319
  - Add before/after/around hooks
107
320
  - Add destroy, and remove actions on show page
108
321
  - Clear tubes.
@@ -112,5 +325,23 @@ Submit a pull request. Follow conventions of the project. Be nice.
112
325
  - Add logging with Job.args in backburner logs
113
326
  - MAYBE - ActiveJob adapter
114
327
 
328
+
329
+ ### Running in Development
330
+
331
+ ```
332
+ cd test/dummy
333
+ bundle exec backburner
334
+ ```
335
+
336
+ ### Releasing
337
+
338
+ 1. `gem bump -v minor -t`
339
+ Where <minor> can be: major|minor|patch|pre|release or a version number
340
+ 2. Edit `CHANGELOG.md` with details from `git log --oneline`
341
+ 3. `git commit --amend`
342
+ 4. `gem release -k nac -p`
343
+ Where <nac> is an authorized key with push capabilities.
344
+
345
+
115
346
  ## License
116
347
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,4 +1,17 @@
1
1
  module Postburner
2
+ # Must implement a perform method, if an exception is raised the job
3
+ # doesn't complete.
4
+ #
5
+ # Job won't run unless queued_at is set, and is set to a time prior to
6
+ # the time the job runs.
7
+ #
8
+ # TODO Mailer uses ActiveJob::Arguments... probably should use that here
9
+ # as well. Decided how to migrate existing jobs or allow both - Opt to
10
+ # allow both: rescue from ActiveJob::DeserializationError and use the
11
+ # plain hash, probably log it too.
12
+ #
13
+ # Add `cancelled_at` that blocks jobs performing if present.
14
+ #
2
15
  class Job < ApplicationRecord
3
16
  include Backburner::Queue
4
17
 
@@ -17,6 +30,8 @@ module Postburner
17
30
  def queue!(options={})
18
31
  return if self.queued_at.present? && self.bkid.present?
19
32
 
33
+ self.save!
34
+
20
35
  case
21
36
  when options[:at].present?
22
37
  # this is rudimentary, add error handling
@@ -33,14 +48,15 @@ module Postburner
33
48
  # tube: backburner.worker.queue.backburner-jobs
34
49
  #
35
50
  def self.perform(id, _={})
51
+ job = nil
36
52
  begin
37
53
  job = self.find(id)
38
- job.perform!(job.args)
39
54
  rescue ActiveRecord::RecordNotFound => e
40
55
  Rails.logger.warn <<-MSG
41
56
  [Postburner::Job] [#{id}] Not Found.
42
57
  MSG
43
58
  end
59
+ job&.perform!(job.args)
44
60
  end
45
61
 
46
62
  def perform!(args={})
@@ -55,52 +71,63 @@ module Postburner
55
71
  )
56
72
 
57
73
  begin
74
+ if self.queued_at.nil?
75
+ self.log! "Not Queued", level: :error
76
+ return
77
+ end
78
+
79
+ if self.queued_at > Time.zone.now
80
+ self.log! "Future Queued", level: :error
81
+ return
82
+ end
83
+
58
84
  if self.processed_at.present?
59
- self.log "Already Processed", level: :error
60
- update_column :logs, self.logs
85
+ self.log! "Already Processed", level: :error
61
86
  self.delete!
62
87
  return
63
88
  end
64
89
 
65
90
  if self.removed_at.present?
66
- self.log "Removed", level: :error
67
- update_column :logs, self.logs
91
+ self.log! "Removed", level: :error
68
92
  return
69
93
  end
70
94
 
71
95
  if self.run_at && self.run_at > Time.zone.now
72
96
  response = self.insert! delay: self.run_at - Time.zone.now
73
- self.log "PREMATURE; RE-INSERTED: #{response}"
74
- update_column :logs, self.logs
97
+ self.log! "PREMATURE; RE-INSERTED: #{response}"
75
98
  return
76
99
  end
77
100
 
78
- self.log('START')
101
+ self.log!('START')
79
102
 
80
- self.perform(args)
103
+ begin
104
+ self.perform(args)
105
+ rescue Exception => exception
106
+ self.persist_metadata!
107
+ self.log! '[Postburner] Exception raised during perform prevented completion.'
108
+ raise exception
109
+ end
81
110
 
82
- self.log('DONE')
111
+ self.log!('DONE')
112
+
113
+ begin
114
+ now = Time.zone.now
115
+ _duration = (now - self.processing_at) * 1000 rescue nil
116
+ persist_metadata!(
117
+ processed_at: now,
118
+ duration: _duration,
119
+ )
120
+ rescue Exception => e
121
+ self.log_exception!(e)
122
+ self.log! '[Postburner] Could not set data after processing.'
123
+ # TODO README doesn't retry if Postburner is to blame
124
+ end
83
125
 
84
- rescue Exception => e
85
- self.log_exception(e)
126
+ rescue Exception => exception
127
+ self.log_exception!(exception)
128
+ raise exception
86
129
  end
87
130
 
88
- begin
89
- now = Time.zone.now
90
- _duration = (now - self.processing_at) * 1000 rescue nil
91
- self.update_columns(
92
- processed_at: now,
93
- duration: _duration,
94
- errata: self.errata,
95
- error_count: self.errata.length,
96
- logs: self.logs,
97
- log_count: self.logs.length,
98
- )
99
- rescue Exception => e
100
- raise e if Rails.env.development? || Rails.env.production?
101
- self.log_exception(e)
102
- update_column :errata, self.errata
103
- end
104
131
  end
105
132
 
106
133
  def delete!
@@ -122,9 +149,12 @@ module Postburner
122
149
  end
123
150
 
124
151
  def remove!
125
- return false if self.attempts.any?
126
- self.delete!
127
- self.update_column(removed_at: Time.zone.now)
152
+ if self.beanstalk_job
153
+ self.delete!
154
+ self.update_column(:removed_at, Time.zone.now)
155
+ else
156
+ false
157
+ end
128
158
  end
129
159
 
130
160
  def beanstalk_job
@@ -152,28 +182,61 @@ module Postburner
152
182
  ]
153
183
  end
154
184
 
185
+ def log_exception!(exception)
186
+ self.log_exception(exception)
187
+ self.update_column :errata, self.errata
188
+ end
189
+
155
190
  def log(message, options={})
156
191
  options[:level] ||= :info
157
192
  options[:level] = :error unless LOG_LEVELS.member?(options[:level])
158
193
 
159
194
  self.logs << [
160
- Time.zone.now,
161
- options[:level],
162
- message,
195
+ Time.zone.now, # time
196
+ {
197
+ level: options[:level], # level
198
+ message: message, # message
199
+ elapsed: self.elapsed_ms, # ms from start
200
+ }
163
201
  ]
164
202
  end
165
203
 
204
+ # ms from attempting_at
205
+ #
206
+ def elapsed_ms
207
+ return unless self.attempting_at
208
+ (Time.zone.now - self.attempting_at) * 1000
209
+ end
210
+
211
+ def log!(message, options={})
212
+ self.log(message, options)
213
+ self.update_column :logs, self.logs
214
+ end
215
+
166
216
  private
167
217
 
218
+ def persist_metadata!(data={})
219
+ self.update_columns({
220
+ errata: self.errata,
221
+ error_count: self.errata.length,
222
+ logs: self.logs,
223
+ log_count: self.logs.length,
224
+ }.merge(data))
225
+ end
226
+
227
+
168
228
  def insert!(options={})
169
- response = Backburner::Worker.enqueue(Postburner::Job, self.id, options)
229
+ response = Backburner::Worker.enqueue(
230
+ Postburner::Job,
231
+ self.id,
232
+ options
233
+ )
170
234
 
171
235
  self.log("QUEUED: #{response}")
172
236
 
173
- update_columns(
237
+ persist_metadata!(
174
238
  queued_at: Time.zone.now,
175
239
  bkid: response[:id],
176
- logs: self.logs,
177
240
  )
178
241
 
179
242
  response
@@ -1,14 +1,14 @@
1
1
  module Postburner
2
2
  # Send a mailer, tracked.
3
3
  #
4
- # Postburner::Mailer.deliver(UserMailer, :welcome, user_id: 1)
5
- # Postburner::Mailer.deliver(UserMailer, :welcome, user_id: 1).queue! at: Time.zone.now + 1.day
6
- # Postburner::Mailer.deliver(UserMailer, :welcome, user_id: 1).queue! delay: 5.minutes
4
+ # Postburner::Mailer.deliver(UserMailer, :welcome).with(user_id: 1)
5
+ # Postburner::Mailer.deliver(UserMailer, :welcome).with(user_id: 1).queue! at: Time.zone.now + 1.day
6
+ # Postburner::Mailer.deliver(UserMailer, :welcome).with(user_id: 1).queue! delay: 5.minutes
7
7
  class Mailer < Job
8
8
  #queue 'mailers'
9
9
 
10
- def self.deliver!(mailer, action)
11
- job = self.create!(
10
+ def self.delivery(mailer, action)
11
+ job = self.new(
12
12
  args: {
13
13
  mailer: mailer.to_s,
14
14
  action: action.to_s,
@@ -17,9 +17,62 @@ module Postburner
17
17
  job
18
18
  end
19
19
 
20
- def process(args)
21
- cls = args['mailer'].constantize
22
- cls.send(args['action']).deliver_now
20
+ def self.delivery!(mailer, action)
21
+ job = self.delivery(mailer, action)
22
+ job.save!
23
+ job
24
+ end
25
+
26
+ # Similar to ActionMailer #with - set the parameters
27
+ #
28
+ def with(params={})
29
+ self.args.merge!(
30
+ 'params' => ActiveJob::Arguments.serialize(params)
31
+ )
32
+ self
33
+ end
34
+
35
+ def with!(params={})
36
+ self.with(params)
37
+ self.save!
38
+ self
39
+ end
40
+
41
+ # Build the mail but don't send.
42
+ #
43
+ # Optional `args` argument for testing convenience.
44
+ #
45
+ def assemble
46
+ mail = self.mailer.with(self.params).send(self.action)
47
+ mail
48
+ end
49
+
50
+ # Get the mailer class.
51
+ #
52
+ def mailer
53
+ self.args['mailer'].constantize
54
+ end
55
+
56
+ # Get the mailer action as a symbol.
57
+ #
58
+ def action
59
+ self.args['action']&.to_sym
60
+ end
61
+
62
+ # Get the deserialized params.
63
+ #
64
+ def params
65
+ ActiveJob::Arguments.deserialize(self.args['params']).to_h
66
+ end
67
+
68
+ def perform(args)
69
+ self.log! "Building"
70
+ mail = self.assemble
71
+
72
+ self.log! "Delivering"
73
+ mail.deliver_now
74
+
75
+ self.log! "Delivered"
23
76
  end
24
77
  end
25
78
  end
@@ -1,3 +1,3 @@
1
1
  module Postburner
2
- VERSION = '0.3.2'
2
+ VERSION = '0.6.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.3.2
4
+ version: 0.6.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: 2021-05-07 00:00:00.000000000 Z
11
+ date: 2021-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -128,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
128
  - !ruby/object:Gem::Version
129
129
  version: '0'
130
130
  requirements: []
131
- rubygems_version: 3.1.4
131
+ rubygems_version: 3.1.6
132
132
  signing_key:
133
133
  specification_version: 4
134
134
  summary: Postgres backed beanstalkd queue via backburner