postburner 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b86343f81143907f3df739be458355fd5ac083cc83c6785a8eb3c45b4f2d2e3c
4
+ data.tar.gz: 2db76cad93eeb4e5fa551ca7b7a5a9734c81b1d50c64acdbba7e5f71d75cc579
5
+ SHA512:
6
+ metadata.gz: 167fd6de8a0e985d09baa86ef49e63c9a7d5e642732e10cc6812dcc2bc562a6e1fc95a3910691a18450dd84ff6440ec69a884cd53f8fb236e12fb032e6fe5a97
7
+ data.tar.gz: 2fb90a8b7a4ad78a8b8c5163bbf9585552fc0e72522d19d0c7779b1706e084899f347932bc5e70741ad64dad83a8bc5a31dae7e07ef8028e20adc4503f778c95
data/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # Changelog
2
+
3
+ ## v0.2.0 - 2021-04-25
4
+
5
+ ### Added
6
+ - add migration generator.
7
+ - move subclasses to app/jobs.
8
+ - fix/expand views. add lag stat.
9
+ - initial commit with concept.
10
+
11
+ ### Fixed
12
+ - update README.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2021 Matt Smith
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.
data/README.md ADDED
@@ -0,0 +1,116 @@
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.
4
+
5
+ It is meant to be complementary to Backburner. Use Backburner as the default
6
+ ActiveJob processor for mailers, active storage, and the like. Use a
7
+ `Postburner::Job` for things that you want to track.
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.
27
+
28
+ ## Usage
29
+
30
+ ```ruby
31
+ class RunDonation < Postburner::Job
32
+ queue 'critical'
33
+ queue_priority 0 # 0 is highest priority
34
+ queue_max_job_retries 0 # don't retry
35
+
36
+ def process(args)
37
+ # do long tasks here
38
+ # also have access to self.args
39
+ end
40
+ end
41
+
42
+ RunDonation.create!(args: {donation_id: 123}).queue!
43
+ => {:status=>"INSERTED", :id=>"1139"}
44
+ RunDonation.create!(args: {donation_id: 123}).queue! at: Time.zone.now + 2.days
45
+ => {:status=>"INSERTED", :id=>"1140"}
46
+
47
+ # `delay` takes priority over `at`
48
+ RunDonation.create!(args: {donation_id: 123}).queue! delay: 1.hour
49
+ => {:status=>"INSERTED", :id=>"1141"}
50
+ ```
51
+
52
+ ## Installation
53
+
54
+ ```ruby
55
+ # in Gemfile
56
+ gem 'postburner'
57
+ ```
58
+
59
+ ```bash
60
+ $ bundle
61
+
62
+ # install migration, possible to edit and add attributes or indexes as needed.
63
+ $ bundle exec rails g postburner:install
64
+ ```
65
+
66
+ Add a `config/initializers/backburner.rb` with option found [here](https://github.com/nesquena/backburner#configuration).
67
+
68
+ Set `Backburner` for `ActiveJob`
69
+ ```
70
+ # config/application.rb
71
+ config.active_job.queue_adapter = :backburner
72
+ ```
73
+
74
+ Postburner may later provide an adapter, but we recommend using `Postburner::Job` classes
75
+ directyly.
76
+
77
+ Add jobs to `app/jobs/`. There currently is no generator.
78
+ ```ruby
79
+ # app/jobs/run_donation.rb
80
+
81
+ class RunDonation < Postburner::Job
82
+ queue 'critical'
83
+ queue_priority 0 # 0 is highest priority
84
+ queue_max_job_retries 0 # don't retry
85
+
86
+ def process(args)
87
+ # do long tasks here
88
+ # also have access to self.args
89
+ end
90
+ end
91
+
92
+ ## Contributing
93
+ Submit a pull request. Follow conventions of the project. Be nice.
94
+
95
+ ### V1 TODO
96
+ - Basic tests
97
+ - Add Authentication modules for engine mount.
98
+
99
+ ### V1+ TODO
100
+ - Install generator
101
+ - Sub to backburner
102
+ - Job generator
103
+ - Build file in app/jobs
104
+ - Inherit from Postburner::Job
105
+ - Job generator
106
+ - Add before/after/around hooks
107
+ - Add destroy, and remove actions on show page
108
+ - Clear tubes.
109
+ - Document how/when to use activerecord hooks
110
+ - Document how/when to use backburner hooks
111
+ - Document how/when to use postburner hooks
112
+ - Add logging with Job.args in backburner logs
113
+ - MAYBE - ActiveJob adapter
114
+
115
+ ## License
116
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
9
+
10
+ require "rake/testtask"
11
+
12
+ Rake::TestTask.new(:test) do |t|
13
+ t.libs << 'test'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = false
16
+ end
17
+
18
+ task default: :test
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/postburner .css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,4 @@
1
+ module Postburner
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,13 @@
1
+ require_dependency "postburner/application_controller"
2
+
3
+ module Postburner
4
+ class JobsController < ApplicationController
5
+ def index
6
+ @jobs = Job.order(queued_at: :desc, created_at: :desc)
7
+ end
8
+
9
+ def show
10
+ @job = Job.find(params[:id])
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ require_dependency "postburner/application_controller"
2
+
3
+ module Postburner
4
+ class StaticController < ApplicationController
5
+ def root
6
+ redirect_to postburner.jobs_url
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ module Postburner
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Postburner
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Postburner
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Postburner
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,196 @@
1
+ module Postburner
2
+ class Job < ApplicationRecord
3
+ include Backburner::Queue
4
+
5
+ LOG_LEVELS = [
6
+ :debug,
7
+ :info,
8
+ :warning,
9
+ :error
10
+ ].freeze
11
+
12
+ before_validation :ensure_sid!
13
+ before_destroy :delete!
14
+
15
+ validates :sid, presence: {strict: true}
16
+
17
+ def queue!(options={})
18
+ return if self.queued_at.present? && self.bkid.present?
19
+
20
+ case
21
+ when options[:at].present?
22
+ # this is rudimentary, add error handling
23
+ options[:delay] ||= options[:at].to_i - Time.zone.now.to_i
24
+ update_column :run_at, options[:at]
25
+ options.delete(:at)
26
+ when options[:delay].present?
27
+ update_column :run_at, Time.zone.now + options[:delay].seconds
28
+ end
29
+
30
+ insert!(options)
31
+ end
32
+
33
+ # tube: backburner.worker.queue.backburner-jobs
34
+ #
35
+ def self.perform(id, _={})
36
+ begin
37
+ job = self.find(id)
38
+ job.perform!(job.args)
39
+ rescue ActiveRecord::RecordNotFound => e
40
+ Rails.logger.warning <<-MSG
41
+ [Postburner::Job] [#{id}] Not Found.
42
+ MSG
43
+ end
44
+ end
45
+
46
+ def perform!(args={})
47
+ self.attempting
48
+
49
+ self.update_columns(
50
+ attempting_at: self.attempting_at,
51
+ attempts: self.attempts,
52
+ attempt_count: self.attempts.length,
53
+ lag: self.lag,
54
+ processing_at: Time.zone.now,
55
+ )
56
+
57
+ begin
58
+ if self.removed_at.present?
59
+ self.log "Removed", level: :error
60
+ update_column :logs, self.logs
61
+ return
62
+ end
63
+
64
+ if self.run_at && self.run_at > Time.zone.now
65
+ response = self.insert! delay: self.run_at - Time.zone.now
66
+ self.log "PREMATURE; RE-INSERTED: #{response}"
67
+ update_column :logs, self.logs
68
+ return
69
+ end
70
+
71
+ self.log('START')
72
+
73
+ self.perform(args)
74
+
75
+ self.log('DONE')
76
+
77
+ rescue Exception => e
78
+ self.log_exception(e)
79
+ end
80
+
81
+ begin
82
+ now = Time.zone.now
83
+ _duration = (now - self.processing_at) * 1000 rescue nil
84
+ self.update_columns(
85
+ processed_at: now,
86
+ duration: _duration,
87
+ errata: self.errata,
88
+ error_count: self.errata.length,
89
+ logs: self.logs,
90
+ log_count: self.logs.length,
91
+ )
92
+ rescue Exception => e
93
+ raise e if Rails.env.development? || Rails.env.production?
94
+ self.log_exception(e)
95
+ update_column :errata, self.errata
96
+ end
97
+ end
98
+
99
+ def delete!
100
+ return unless self.beanstalk_job
101
+ begin
102
+ self.beanstalk_job.delete
103
+ rescue Beaneater::NotConnected => e
104
+ self.beanstalk_job!.delete
105
+ end
106
+ end
107
+
108
+ def kick!
109
+ return unless self.beanstalk_job
110
+ begin
111
+ self.beanstalk_job.kick
112
+ rescue Beaneater::NotConnected => e
113
+ self.beanstalk_job!.kick
114
+ end
115
+ end
116
+
117
+ def remove!
118
+ return false if self.attempts.any?
119
+ self.delete!
120
+ self.update_column(removed_at: Time.zone.now)
121
+ end
122
+
123
+ def beanstalk_job
124
+ return unless self.bkid.present?
125
+ return @_beanstalk_job if @_beanstalk_job
126
+
127
+ @_beanstalk_job = Postburner.connection.beanstalk.jobs.find(self.bkid)
128
+
129
+ @_beanstalk_job
130
+ end
131
+
132
+ def beanstalk_job!
133
+ @_beanstalk_job = nil
134
+ self.beanstalk_job
135
+ end
136
+
137
+ def log_exception(exception)
138
+ self.errata << [
139
+ Time.zone.now,
140
+ {
141
+ class: exception.class,
142
+ message: exception.message,
143
+ backtrace: exception.backtrace,
144
+ }
145
+ ]
146
+ end
147
+
148
+ def log(message, options={})
149
+ options[:level] ||= :info
150
+ options[:level] = :error unless LOG_LEVELS.member?(options[:level])
151
+
152
+ self.logs << [
153
+ Time.zone.now,
154
+ options[:level],
155
+ message,
156
+ ]
157
+ end
158
+
159
+ private
160
+
161
+ def insert!(options={})
162
+ response = Backburner::Worker.enqueue(Postburner::Job, self.id, options)
163
+
164
+ self.log("QUEUED: #{response}")
165
+
166
+ update_columns(
167
+ queued_at: Time.zone.now,
168
+ bkid: response[:id],
169
+ logs: self.logs,
170
+ )
171
+
172
+ response
173
+ end
174
+
175
+ def attempting
176
+ now = Time.zone.now
177
+ self.attempts << now
178
+ self.attempting_at ||= now
179
+ self.lag ||= (self.attempting_at - self.intended_at) * 1000
180
+ now
181
+ end
182
+
183
+ def intended_at
184
+ self.run_at ? self.run_at : self.queued_at
185
+ end
186
+
187
+ def ensure_sid!
188
+ self.sid ||= SecureRandom.uuid
189
+ end
190
+
191
+ def message
192
+ "Job: #{self.id}"
193
+ end
194
+
195
+ end
196
+ end
@@ -0,0 +1,10 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
5
+ %title Postburner
6
+ = csrf_meta_tags
7
+ = csp_meta_tag
8
+ = stylesheet_link_tag "postburner/application", media: "all"
9
+ %body
10
+ = yield
@@ -0,0 +1,34 @@
1
+ %h1 Jobs
2
+
3
+ %table
4
+ %thead
5
+ %tr
6
+ %th ID
7
+ %th Beanstalk
8
+ %th Type
9
+ %th Arguments
10
+ %th Run
11
+ %th Attempted
12
+ %th Completed
13
+ %th Attempts
14
+ %th Errors
15
+ %th Logs
16
+ %th Lag
17
+ %th Duration
18
+ %tbody
19
+ - @jobs.each do |job|
20
+ %tr
21
+ %td
22
+ = link_to postburner.job_path(job) do
23
+ %span{title: job.sid}= job.id
24
+ %td= job.bkid
25
+ %td= job.type
26
+ %td= job.args.inspect
27
+ %td= job.run_at
28
+ %td= job.attempting_at
29
+ %td= job.processed_at
30
+ %td= job.attempt_count
31
+ %td= job.error_count
32
+ %td= job.log_count
33
+ %td= job.lag
34
+ %td= job.duration
@@ -0,0 +1,13 @@
1
+ %h1 Job #{@job.id} / #{@job.bkid} / #{@job.sid}
2
+
3
+ - if @job.run_at && @job.run_at > Time.zone.now
4
+ Running in
5
+ = distance_of_time_in_words Time.zone.now, @job.run_at
6
+ (#{@job.run_at.to_i - Time.zone.now.to_i} seconds)
7
+
8
+ %h3 Stats
9
+ - if @job.beanstalk_job
10
+ %pre= JSON.pretty_generate @job.beanstalk_job.stats.as_json
11
+
12
+ %h3 Job
13
+ %pre= JSON.pretty_generate @job.as_json
File without changes
data/config/routes.rb ADDED
@@ -0,0 +1,6 @@
1
+ Postburner::Engine.routes.draw do
2
+ root 'static#root'
3
+ resources :jobs, only: %w(index show destroy) do
4
+ patch :remove, on: :member
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ bin/rails generate install Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,47 @@
1
+ class Postburner::InstallGenerator < Rails::Generators::Base
2
+ source_root File.expand_path('templates', __dir__)
3
+ include Rails::Generators::Migration
4
+
5
+ def install_migrations
6
+ install_migration! 'create_postburner_jobs'
7
+ end
8
+
9
+ def self.next_migration_number(dirname)
10
+ timestamp = Time.now.utc.strftime("%Y%m%d%H%M%S")
11
+ stem = timestamp[0..-3]
12
+ regexp = Regexp.new("^(#{stem})(\\d\\d)_")
13
+ timestamps = Dir[File.join(dirname, '*.rb')].map { |name|
14
+ match = regexp.match(File.basename(name, File.extname(name)))
15
+ match ? match[2].to_i : nil
16
+ }.reject(&:nil?)
17
+ _max = timestamps.max || timestamp[-2..-1].to_i
18
+ _next = _max + 1
19
+ raise "MISSING NEXT" if _next.blank?
20
+ migration_number = "#{stem}#{_next}"
21
+ if migration_number.length != 14
22
+ raise "INCORRECT LENGTH stem=#{stem} _next=#{_next} _max=#{_max}"
23
+ end
24
+ migration_number
25
+ end
26
+
27
+ private
28
+
29
+ def install_migration!(filename)
30
+ migrate_path = File.join(Rails.root, "db/migrate")
31
+
32
+ if self.class.migration_exists?(migrate_path, "#{filename}")
33
+ say_status "skipped", "#{filename}.rb migration already exists"
34
+ else
35
+ migration_template(
36
+ "migrations/#{filename}.rb.erb",
37
+ File.join(migrate_path, "#{filename}.rb"),
38
+ migration_version: migration_version,
39
+ )
40
+ end
41
+ end
42
+
43
+ def migration_version
44
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
45
+ end
46
+
47
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ class CreatePostburnerJobs < ActiveRecord::Migration<%= migration_version %>
4
+ def change
5
+ create_table :postburner_jobs do |t|
6
+ t.bigint :bkid
7
+ t.string :sid, null: false
8
+ t.string :type
9
+ t.jsonb :args, default: {}
10
+ t.datetime :run_at
11
+ t.datetime :queued_at
12
+ t.datetime :attempting_at
13
+ t.datetime :processing_at
14
+ t.datetime :processed_at
15
+ t.datetime :removed_at
16
+ t.integer :lag
17
+ t.integer :duration
18
+ t.integer :attempt_count
19
+ t.integer :error_count
20
+ t.integer :log_count
21
+ t.datetime :attempts, array: true, default: []
22
+ t.jsonb :errata, default: []
23
+ t.jsonb :logs, default: []
24
+
25
+ t.timestamps
26
+
27
+ t.index [ :bkid ]
28
+ t.index [ :sid ], unique: true
29
+ t.index [ :type ]
30
+ t.index [ :args ], using: :gin
31
+ t.index [ :run_at ]
32
+ t.index [ :queued_at ]
33
+ t.index [ :removed_at ]
34
+ t.index [ :lag ]
35
+ t.index [ :duration ]
36
+ t.index [ :attempt_count ]
37
+ t.index [ :error_count ]
38
+ t.index [ :log_count ]
39
+
40
+ # Add these or more depending on what you want to search for.
41
+ #t.index [ :attempts ], using: :gin
42
+ #t.index [ :errata ], using: :gin
43
+ #t.index [ :logs ], using: :gin
44
+ end
45
+ end
46
+ end
data/lib/postburner.rb ADDED
@@ -0,0 +1,31 @@
1
+ require "postburner/version"
2
+ require "postburner/engine"
3
+
4
+ module Postburner
5
+
6
+ def self.connection
7
+ @_connection ||= Backburner::Connection.new(
8
+ Backburner.configuration.beanstalk_url
9
+ )
10
+ @_connection.reconnect! unless @_connection.connected?
11
+ @_connection
12
+ end
13
+
14
+ def self.connected
15
+ if block_given?
16
+ begin
17
+ yield connection
18
+ ensure
19
+ connection.close if connection
20
+ end
21
+ else
22
+ connection
23
+ end
24
+ end
25
+
26
+ def self.remove_all!(confirm)
27
+ return unless confirm == "CONFIRM"
28
+
29
+ # TODO
30
+ end
31
+ end
@@ -0,0 +1,17 @@
1
+ require 'backburner'
2
+ require 'haml-rails'
3
+
4
+ module Postburner
5
+ class Engine < ::Rails::Engine
6
+ isolate_namespace Postburner
7
+
8
+ config.generators do |g|
9
+ g.template_engine :haml
10
+ g.helper false
11
+ g.fixture false
12
+ g.assets false
13
+ g.skip_routes true
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Postburner
2
+ VERSION = '0.2.2'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :postburner do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: postburner
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ platform: ruby
6
+ authors:
7
+ - Matt Smith
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-05-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 6.1.3
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 6.1.3.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 6.1.3
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 6.1.3.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: backburner
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 1.5.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.5.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: pg
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.2.3
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.2.3
61
+ - !ruby/object:Gem::Dependency
62
+ name: haml-rails
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 2.0.1
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 2.0.1
75
+ description: Queue background jobs, inspect them, and audit them afterwards.
76
+ email:
77
+ - matt@nearapogee.com
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - CHANGELOG.md
83
+ - MIT-LICENSE
84
+ - README.md
85
+ - Rakefile
86
+ - app/assets/config/postburner_manifest.js
87
+ - app/assets/stylesheets/postburner/application.css
88
+ - app/controllers/postburner/application_controller.rb
89
+ - app/controllers/postburner/jobs_controller.rb
90
+ - app/controllers/postburner/static_controller.rb
91
+ - app/helpers/postburner/application_helper.rb
92
+ - app/jobs/postburner/application_job.rb
93
+ - app/mailers/postburner/application_mailer.rb
94
+ - app/models/postburner/application_record.rb
95
+ - app/models/postburner/job.rb
96
+ - app/views/layouts/postburner/application.html.haml
97
+ - app/views/postburner/jobs/index.html.haml
98
+ - app/views/postburner/jobs/show.html.haml
99
+ - config/environment.rb
100
+ - config/routes.rb
101
+ - lib/generators/postburner/install/USAGE
102
+ - lib/generators/postburner/install/install_generator.rb
103
+ - lib/generators/postburner/install/templates/migrations/create_postburner_jobs.rb.erb
104
+ - lib/postburner.rb
105
+ - lib/postburner/engine.rb
106
+ - lib/postburner/version.rb
107
+ - lib/tasks/postburner_tasks.rake
108
+ homepage: https://gitlab.nearapogee.com/opensource/postburner
109
+ licenses:
110
+ - MIT
111
+ metadata:
112
+ homepage_uri: https://gitlab.nearapogee.com/opensource/postburner
113
+ source_code_uri: https://gitlab.nearapogee.com/opensource/postburner
114
+ changelog_uri: https://gitlab.nearapogee.com/opensource/postburner/-/blob/master/CHANGELOG.md
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubygems_version: 3.1.4
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: Postgres backed beanstalkd queue via backburner
134
+ test_files: []