good_job 1.3.5 → 1.3.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46b04fbfe44919834c406101ee18f2b53f5cc05e076525f7243e346fa966ca94
4
- data.tar.gz: 798738a1f2b0c7f21457921c2c640cdc78151a09262dfa7d8a383e8778282b9d
3
+ metadata.gz: 8b5d625792328475faca2679c6718f344fc5162cac639be09f91197c998f2fdf
4
+ data.tar.gz: 4aef2c4ae814f2a0606c18e875c91e56f8a1411394c37d45f4e1141be719f080
5
5
  SHA512:
6
- metadata.gz: 841c85e7b4d9fa28d1fcdbb7c6a48771438f24ae33a264a80afdff1c9730a3438b98aa5d82f54bd1d4c979b2dab64997fbf6d64036bc96fdac6c851f70e0f68f
7
- data.tar.gz: 9c2d11c56e3db986aa5bbecc85a317396a19ba1c838b97d32cd16f21b9cd29b6c154be817879d8c8a8925da645d298442c0ebc39aba3d5bba707ed01558b55c5
6
+ metadata.gz: d309e288c89c65ec809cf7f9e138026b229aed9abb6ee667343c56ed1e96fb0833be36b7e1f1c6b064168957f537d572e2ceb5ecad0f6e754108762ace9fbd3b
7
+ data.tar.gz: c1b83122c14edcbe619c6198fae270f9dbb0398888232f96e8956be23ca0f5798422181a21ea08735a0089ad3a92c0405ee69731a8a205f3fe9c99ba2b27bb36
@@ -1,9 +1,37 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.3.6](https://github.com/bensheldon/good_job/tree/v1.3.6) (2020-12-30)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.3.5...v1.3.6)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Call GoodJob.on\_thread\_error when Notifier thread raises exception [\#185](https://github.com/bensheldon/good_job/pull/185) ([bensheldon](https://github.com/bensheldon))
10
+ - Improve dashboard UI, fix button state, add unfiltering [\#181](https://github.com/bensheldon/good_job/pull/181) ([bensheldon](https://github.com/bensheldon))
11
+
12
+ **Fixed bugs:**
13
+
14
+ - Replace ActiveRecord execute usage and avoid potential memory leakage [\#187](https://github.com/bensheldon/good_job/issues/187)
15
+ - Does good\_job hold on to advisory locks for finished jobs? [\#177](https://github.com/bensheldon/good_job/issues/177)
16
+
17
+ **Merged pull requests:**
18
+
19
+ - Run tests with Rails default configuration to enable Zeitwerk [\#190](https://github.com/bensheldon/good_job/pull/190) ([bensheldon](https://github.com/bensheldon))
20
+ - Update all Lockable queries to use exec\_query instead of execute; clear async\_exec results [\#189](https://github.com/bensheldon/good_job/pull/189) ([bensheldon](https://github.com/bensheldon))
21
+ - Have Lockable\#advisory\_locked? directly query pg\_locks table [\#188](https://github.com/bensheldon/good_job/pull/188) ([bensheldon](https://github.com/bensheldon))
22
+ - Update development gems, including Rails v6.1 and Rails HEAD [\#186](https://github.com/bensheldon/good_job/pull/186) ([bensheldon](https://github.com/bensheldon))
23
+ - Update Appraisals for Rails 6.1 [\#183](https://github.com/bensheldon/good_job/pull/183) ([bensheldon](https://github.com/bensheldon))
24
+ - Add Ruby 3 to CI test matrix [\#182](https://github.com/bensheldon/good_job/pull/182) ([bensheldon](https://github.com/bensheldon))
25
+
3
26
  ## [v1.3.5](https://github.com/bensheldon/good_job/tree/v1.3.5) (2020-12-17)
4
27
 
5
28
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.3.4...v1.3.5)
6
29
 
30
+ **Fixed bugs:**
31
+
32
+ - Ensure advisory lock CTE is MATERIALIZED on Postgres v12+ [\#179](https://github.com/bensheldon/good_job/pull/179) ([bensheldon](https://github.com/bensheldon))
33
+ - Ensure that deleted jobs are unlocked [\#178](https://github.com/bensheldon/good_job/pull/178) ([bensheldon](https://github.com/bensheldon))
34
+
7
35
  **Closed issues:**
8
36
 
9
37
  - not running jobs [\#168](https://github.com/bensheldon/good_job/issues/168)
@@ -11,15 +39,13 @@
11
39
 
12
40
  **Merged pull requests:**
13
41
 
14
- - Ensure advisory lock CTE is MATERIALIZED on Postgres v12+ [\#179](https://github.com/bensheldon/good_job/pull/179) ([bensheldon](https://github.com/bensheldon))
15
- - Ensure that deleted jobs are unlocked [\#178](https://github.com/bensheldon/good_job/pull/178) ([bensheldon](https://github.com/bensheldon))
16
42
  - Add Appraisal for Rails 6.1-rc2 [\#175](https://github.com/bensheldon/good_job/pull/175) ([bensheldon](https://github.com/bensheldon))
17
43
 
18
44
  ## [v1.3.4](https://github.com/bensheldon/good_job/tree/v1.3.4) (2020-12-02)
19
45
 
20
46
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.3.3...v1.3.4)
21
47
 
22
- **Merged pull requests:**
48
+ **Fixed bugs:**
23
49
 
24
50
  - Fix job ordering for Rails 6.1 [\#174](https://github.com/bensheldon/good_job/pull/174) ([morgoth](https://github.com/morgoth))
25
51
 
@@ -27,7 +53,7 @@
27
53
 
28
54
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.3.2...v1.3.3)
29
55
 
30
- **Merged pull requests:**
56
+ **Implemented enhancements:**
31
57
 
32
58
  - UI: Admin UI with filters and space efficient layout [\#173](https://github.com/bensheldon/good_job/pull/173) ([zealot128](https://github.com/zealot128))
33
59
 
@@ -428,6 +454,7 @@
428
454
  **Merged pull requests:**
429
455
 
430
456
  - Improve ActiveRecord usage for advisory locking [\#24](https://github.com/bensheldon/good_job/pull/24) ([bensheldon](https://github.com/bensheldon))
457
+ - Remove support for Rails 5.1 [\#23](https://github.com/bensheldon/good_job/pull/23) ([bensheldon](https://github.com/bensheldon))
431
458
 
432
459
  ## [v0.3.0](https://github.com/bensheldon/good_job/tree/v0.3.0) (2020-03-22)
433
460
 
@@ -446,7 +473,6 @@
446
473
 
447
474
  **Merged pull requests:**
448
475
 
449
- - Remove support for Rails 5.1 [\#23](https://github.com/bensheldon/good_job/pull/23) ([bensheldon](https://github.com/bensheldon))
450
476
  - Gracefully shutdown Scheduler when executable receives TERM or INT [\#17](https://github.com/bensheldon/good_job/pull/17) ([bensheldon](https://github.com/bensheldon))
451
477
  - Update Appraisals [\#16](https://github.com/bensheldon/good_job/pull/16) ([bensheldon](https://github.com/bensheldon))
452
478
 
@@ -42,11 +42,11 @@ module GoodJob
42
42
  GoodJob::Job.group("serialized_params->>'job_class'").count
43
43
  end
44
44
 
45
- def to_query(override)
45
+ def to_params(override)
46
46
  {
47
47
  state: params[:state],
48
48
  job_class: params[:job_class],
49
- }.merge(override).delete_if { |_, v| v.nil? }.to_query
49
+ }.merge(override).delete_if { |_, v| v.nil? }
50
50
  end
51
51
  end
52
52
 
@@ -8,18 +8,30 @@
8
8
  <small>Filter by job class</small>
9
9
  <br>
10
10
  <% @filter.job_classes.each do |name, count| %>
11
- <a href='<%= request.path + "?#{@filter.to_query(job_class: name)}" %>' class='btn btn-sm btn-outline-secondary <%= "active" if params[:job_class] == name %>'>
12
- <%= name %> (<%= count %>)
13
- </a>
11
+ <% if params[:job_class] == name %>
12
+ <%= link_to(root_path(@filter.to_params(job_class: nil)), class: 'btn btn-sm btn-outline-secondary active', role: "button", "aria-pressed": true) do %>
13
+ <%= name %> (<%= count %>)
14
+ <% end %>
15
+ <% else %>
16
+ <%= link_to(root_path(@filter.to_params(job_class: name)), class: 'btn btn-sm btn-outline-secondary', role: "button") do %>
17
+ <%= name %> (<%= count %>)
18
+ <% end %>
19
+ <% end %>
14
20
  <% end %>
15
21
  </div>
16
22
  <div>
17
23
  <small>Filter by state</small>
18
24
  <br>
19
25
  <% @filter.states.each do |name, count| %>
20
- <a href='<%= request.path + "?#{@filter.to_query(state: name)}" %>' class='btn btn-sm btn-outline-secondary <%= "active" if params[:state] == name %>'>
21
- <%= name %> (<%= count %>)
22
- </a>
26
+ <% if params[:state] == name %>
27
+ <%= link_to(root_path(@filter.to_params(state: nil)), class: 'btn btn-sm btn-outline-secondary active', role: "button", "aria-pressed": true) do %>
28
+ <%= name %> (<%= count %>)
29
+ <% end %>
30
+ <% else %>
31
+ <%= link_to(root_path(@filter.to_params(state: name)), class: 'btn btn-sm btn-outline-secondary', role: "button") do %>
32
+ <%= name %> (<%= count %>)
33
+ <% end %>
34
+ <% end %>
23
35
  <% end %>
24
36
  </div>
25
37
  </div>
@@ -28,7 +40,7 @@
28
40
  <% if @filter.jobs.present? %>
29
41
  <%= render 'shared/jobs_table', jobs: @filter.jobs %>
30
42
 
31
- <nav aria-label="Job pagination">
43
+ <nav aria-label="Job pagination" class="mt-3">
32
44
  <ul class="pagination">
33
45
  <li class="page-item">
34
46
  <%= link_to({ after_scheduled_at: (@filter.last.scheduled_at || @filter.last.created_at), after_id: @filter.last.id }, class: "page-link") do %>
@@ -6,14 +6,14 @@
6
6
  <%= csp_meta_tag %>
7
7
 
8
8
  <style>
9
- <%= render file: GoodJob::Engine.root.join("app", "assets", "vendor", "bootstrap", "bootstrap.css") %>
10
- <%= render file: GoodJob::Engine.root.join("app", "assets", "vendor", "chartist", "chartist.css") %>
11
- <%= render file: GoodJob::Engine.root.join("app", "assets", "style.css") %>
9
+ <%== render file: GoodJob::Engine.root.join("app", "assets", "vendor", "bootstrap", "bootstrap.css") %>
10
+ <%== render file: GoodJob::Engine.root.join("app", "assets", "vendor", "chartist", "chartist.css") %>
11
+ <%== render file: GoodJob::Engine.root.join("app", "assets", "style.css") %>
12
12
  </style>
13
13
 
14
14
  <script>
15
- <%= render file: GoodJob::Engine.root.join("app", "assets", "vendor", "bootstrap", "bootstrap-native.js") %>
16
- <%= render file: GoodJob::Engine.root.join("app", "assets", "vendor", "chartist", "chartist.js") %>
15
+ <%== render file: GoodJob::Engine.root.join("app", "assets", "vendor", "bootstrap", "bootstrap-native.js") %>
16
+ <%== render file: GoodJob::Engine.root.join("app", "assets", "vendor", "chartist", "chartist.js") %>
17
17
  </script>
18
18
  </head>
19
19
  <body>
@@ -1,7 +1,7 @@
1
1
  <div id="chart"></div>
2
2
 
3
3
  <script>
4
- new Chartist.Line('#chart', <%= raw chart_data.to_json %>, {
4
+ new Chartist.Line('#chart', <%== chart_data.to_json %>, {
5
5
  height: '300px',
6
6
  fullWidth: true,
7
7
  chartPadding: {
@@ -1,26 +1,28 @@
1
- <div class="table-responsive">
2
- <table class="table table-bordered table-hover table-sm">
3
- <thead>
4
- <th>GoodJob ID</th>
5
- <th>ActiveJob ID</th>
6
- <th>Job Class</th>
7
- <th>Queue</th>
8
- <th>Scheduled At</th>
9
- <th>Error</th>
10
- <th>ActiveJob Params</th>
11
- </thead>
12
- <tbody>
13
- <% jobs.each do |job| %>
14
- <tr id="<%= dom_id(job) %>">
15
- <td><%= link_to job.id, active_job_path(job.serialized_params['job_id'], anchor: dom_id(job)) %></td>
16
- <td><%= link_to job.serialized_params['job_id'], active_job_path(job.serialized_params['job_id']) %></td>
17
- <td><%= job.serialized_params['job_class'] %></td>
18
- <td><%= job.queue_name %></td>
19
- <td><%= job.scheduled_at || job.created_at %></td>
20
- <td><%= job.error %></td>
21
- <td><pre><%= JSON.pretty_generate(job.serialized_params) %></pre></td>
22
- </tr>
23
- <% end %>
24
- </tbody>
25
- </table>
1
+ <div class="card my-3">
2
+ <div class="table-responsive">
3
+ <table class="table card-table table-bordered table-hover table-sm mb-0">
4
+ <thead>
5
+ <th>GoodJob ID</th>
6
+ <th>ActiveJob ID</th>
7
+ <th>Job Class</th>
8
+ <th>Queue</th>
9
+ <th>Scheduled At</th>
10
+ <th>Error</th>
11
+ <th>ActiveJob Params</th>
12
+ </thead>
13
+ <tbody>
14
+ <% jobs.each do |job| %>
15
+ <tr id="<%= dom_id(job) %>">
16
+ <td><%= link_to job.id, active_job_path(job.serialized_params['job_id'], anchor: dom_id(job)) %></td>
17
+ <td><%= link_to job.serialized_params['job_id'], active_job_path(job.serialized_params['job_id']) %></td>
18
+ <td><%= job.serialized_params['job_class'] %></td>
19
+ <td><%= job.queue_name %></td>
20
+ <td><%= job.scheduled_at || job.created_at %></td>
21
+ <td><%= job.error %></td>
22
+ <td><pre><%= JSON.pretty_generate(job.serialized_params) %></pre></td>
23
+ </tr>
24
+ <% end %>
25
+ </tbody>
26
+ </table>
27
+ </div>
26
28
  </div>
@@ -58,9 +58,7 @@ module GoodJob
58
58
  def rails_execution_mode
59
59
  if execution_mode(default: nil)
60
60
  execution_mode
61
- elsif Rails.env.development?
62
- :inline
63
- elsif Rails.env.test?
61
+ elsif Rails.env.development? || Rails.env.test?
64
62
  :inline
65
63
  else
66
64
  :external
@@ -139,7 +139,7 @@ module GoodJob
139
139
  unfinished.priority_ordered.only_scheduled.limit(1).with_advisory_lock do |good_jobs|
140
140
  good_job = good_jobs.first
141
141
  # TODO: Determine why some records are fetched without an advisory lock at all
142
- break unless good_job&.owns_advisory_lock?
142
+ break unless good_job&.executable?
143
143
 
144
144
  result, error = good_job.perform
145
145
  end
@@ -216,6 +216,12 @@ module GoodJob
216
216
  [result, job_error]
217
217
  end
218
218
 
219
+ # Tests whether this job is safe to be executed by this thread.
220
+ # @return [Boolean]
221
+ def executable?
222
+ self.class.unscoped.unfinished.owns_advisory_locked.exists?(id: id)
223
+ end
224
+
219
225
  private
220
226
 
221
227
  def execute
@@ -141,9 +141,9 @@ module GoodJob
141
141
  end
142
142
 
143
143
  def supports_cte_materialization_specifiers?
144
- return @supports_cte_materialization_specifiers if defined?(@supports_cte_materialization_specifiers)
144
+ return @_supports_cte_materialization_specifiers if defined?(@_supports_cte_materialization_specifiers)
145
145
 
146
- @supports_cte_materialization_specifiers = ActiveRecord::Base.connection.postgresql_version >= 120000
146
+ @_supports_cte_materialization_specifiers = ActiveRecord::Base.connection.postgresql_version >= 120000
147
147
  end
148
148
  end
149
149
 
@@ -153,10 +153,11 @@ module GoodJob
153
153
  # all remaining locks).
154
154
  # @return [Boolean] whether the lock was acquired.
155
155
  def advisory_lock
156
- where_sql = <<~SQL.squish
157
- pg_try_advisory_lock(('x' || substr(md5(:table_name || :id::text), 1, 16))::bit(64)::bigint)
156
+ query = <<~SQL.squish
157
+ SELECT 1 AS one
158
+ WHERE pg_try_advisory_lock(('x'||substr(md5($1 || $2::text), 1, 16))::bit(64)::bigint)
158
159
  SQL
159
- self.class.unscoped.exists?([where_sql, { table_name: self.class.table_name, id: send(self.class.primary_key) }])
160
+ self.class.connection.exec_query(query, 'GoodJob::Lockable Advisory Lock', [[nil, self.class.table_name], [nil, send(self.class.primary_key)]]).any?
160
161
  end
161
162
 
162
163
  # Releases an advisory lock on this record if it is locked by this database
@@ -166,9 +167,9 @@ module GoodJob
166
167
  def advisory_unlock
167
168
  query = <<~SQL.squish
168
169
  SELECT 1 AS one
169
- WHERE pg_advisory_unlock(('x'||substr(md5(:table_name || :id::text), 1, 16))::bit(64)::bigint)
170
+ WHERE pg_advisory_unlock(('x'||substr(md5($1 || $2::text), 1, 16))::bit(64)::bigint)
170
171
  SQL
171
- self.class.connection.execute(sanitize_sql_for_conditions([query, { table_name: self.class.table_name, id: send(self.class.primary_key) }])).ntuples.positive?
172
+ self.class.connection.exec_query(query, 'GoodJob::Lockable Advisory Unlock', [[nil, self.class.table_name], [nil, send(self.class.primary_key)]]).any?
172
173
  end
173
174
 
174
175
  # Acquires an advisory lock on this record or raises
@@ -205,13 +206,30 @@ module GoodJob
205
206
  # Tests whether this record has an advisory lock on it.
206
207
  # @return [Boolean]
207
208
  def advisory_locked?
208
- self.class.unscoped.advisory_locked.exists?(id: send(self.class.primary_key))
209
+ query = <<~SQL.squish
210
+ SELECT 1 AS one
211
+ FROM pg_locks
212
+ WHERE pg_locks.locktype = 'advisory'
213
+ AND pg_locks.objsubid = 1
214
+ AND pg_locks.classid = ('x' || substr(md5($1 || $2::text), 1, 16))::bit(32)::int
215
+ AND pg_locks.objid = (('x' || substr(md5($1 || $2::text), 1, 16))::bit(64) << 32)::bit(32)::int
216
+ SQL
217
+ self.class.connection.exec_query(query, 'GoodJob::Lockable Advisory Locked?', [[nil, self.class.table_name], [nil, send(self.class.primary_key)]]).any?
209
218
  end
210
219
 
211
220
  # Tests whether this record is locked by the current database session.
212
221
  # @return [Boolean]
213
222
  def owns_advisory_lock?
214
- self.class.unscoped.owns_advisory_locked.exists?(id: send(self.class.primary_key))
223
+ query = <<~SQL.squish
224
+ SELECT 1 AS one
225
+ FROM pg_locks
226
+ WHERE pg_locks.locktype = 'advisory'
227
+ AND pg_locks.objsubid = 1
228
+ AND pg_locks.classid = ('x' || substr(md5($1 || $2::text), 1, 16))::bit(32)::int
229
+ AND pg_locks.objid = (('x' || substr(md5($1 || $2::text), 1, 16))::bit(64) << 32)::bit(32)::int
230
+ AND pg_locks.pid = pg_backend_pid()
231
+ SQL
232
+ self.class.connection.exec_query(query, 'GoodJob::Lockable Owns Advisory Lock?', [[nil, self.class.table_name], [nil, send(self.class.primary_key)]]).any?
215
233
  end
216
234
 
217
235
  # Releases all advisory locks on the record that are held by the current
@@ -218,13 +218,13 @@ module GoodJob
218
218
  #
219
219
  %w(info debug warn error fatal unknown).each do |level|
220
220
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
221
- def #{level}(progname = nil, tags: [], &block)
222
- return unless logger
223
-
224
- tag_logger(*tags) do
225
- logger.#{level}(progname, &block)
226
- end
227
- end
221
+ def #{level}(progname = nil, tags: [], &block) # def info(progname = nil, tags: [], &block)
222
+ return unless logger # return unless logger
223
+ #
224
+ tag_logger(*tags) do # tag_logger(*tags) do
225
+ logger.#{level}(progname, &block) # logger.info(progname, &block)
226
+ end # end
227
+ end #
228
228
  METHOD
229
229
  end
230
230
  end
@@ -90,6 +90,18 @@ module GoodJob # :nodoc:
90
90
  !@pool.running?
91
91
  end
92
92
 
93
+ # Invoked on completion of ThreadPoolExecutor task
94
+ # @!visibility private
95
+ # @return [void]
96
+ def listen_observer(_time, _result, thread_error)
97
+ if thread_error
98
+ GoodJob.on_thread_error.call(thread_error) if GoodJob.on_thread_error.respond_to?(:call)
99
+ ActiveSupport::Notifications.instrument("notifier_notify_error.good_job", { error: thread_error })
100
+ end
101
+
102
+ listen unless shutdown?
103
+ end
104
+
93
105
  private
94
106
 
95
107
  def create_pool
@@ -100,7 +112,7 @@ module GoodJob # :nodoc:
100
112
  future = Concurrent::Future.new(args: [@recipients, @pool, @listening], executor: @pool) do |recipients, pool, listening|
101
113
  with_listen_connection do |conn|
102
114
  ActiveSupport::Notifications.instrument("notifier_listen.good_job") do
103
- conn.async_exec "LISTEN #{CHANNEL}"
115
+ conn.async_exec("LISTEN #{CHANNEL}").clear
104
116
  end
105
117
 
106
118
  ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
@@ -120,14 +132,11 @@ module GoodJob # :nodoc:
120
132
  listening.make_false
121
133
  end
122
134
  end
123
- end
124
- rescue StandardError => e
125
- ActiveSupport::Notifications.instrument("notifier_notify_error.good_job", { error: e })
126
- raise
127
- ensure
128
- @listening.make_false
129
- ActiveSupport::Notifications.instrument("notifier_unlisten.good_job") do
130
- conn.async_exec "UNLISTEN *"
135
+ ensure
136
+ listening.make_false
137
+ ActiveSupport::Notifications.instrument("notifier_unlisten.good_job") do
138
+ conn.async_exec("UNLISTEN *").clear
139
+ end
131
140
  end
132
141
  end
133
142
 
@@ -135,16 +144,12 @@ module GoodJob # :nodoc:
135
144
  future.execute
136
145
  end
137
146
 
138
- def listen_observer(_time, _result, _thread_error)
139
- listen unless shutdown?
140
- end
141
-
142
147
  def with_listen_connection
143
148
  ar_conn = ActiveRecord::Base.connection_pool.checkout.tap do |conn|
144
149
  ActiveRecord::Base.connection_pool.remove(conn)
145
150
  end
146
151
  pg_conn = ar_conn.raw_connection
147
- pg_conn.exec("SET application_name = #{pg_conn.escape_identifier(self.class.name)}")
152
+ pg_conn.async_exec("SET application_name = #{pg_conn.escape_identifier(self.class.name)}").clear
148
153
  yield pg_conn
149
154
  ensure
150
155
  ar_conn&.disconnect!
@@ -1,4 +1,4 @@
1
1
  module GoodJob
2
2
  # GoodJob gem version.
3
- VERSION = '1.3.5'.freeze
3
+ VERSION = '1.3.6'.freeze
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: good_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.5
4
+ version: 1.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Sheldon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-17 00:00:00.000000000 Z
11
+ date: 2020-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -441,7 +441,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
441
441
  - !ruby/object:Gem::Version
442
442
  version: '0'
443
443
  requirements: []
444
- rubygems_version: 3.1.4
444
+ rubygems_version: 3.2.3
445
445
  signing_key:
446
446
  specification_version: 4
447
447
  summary: A multithreaded, Postgres-based ActiveJob backend for Ruby on Rails