good_job 2.9.2 → 2.9.6

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: 43a641edf5b6ff33dc8752874c6b317ad96bfd74ed4cbcb3a9bbeee7ff9c14cf
4
- data.tar.gz: bfcf81a0d6c2d7bef01c3abdad9222fcc92cc8a5fd0ead3059fe5b9afd96aefa
3
+ metadata.gz: 64642ab1c4e807f67310c70fca0d57ae636955b923dbf1c9a0e09a88a4c66a5d
4
+ data.tar.gz: 69a4d004af970032be6583bfd5a7281c3ee185dedbeb7250cb7d64d9adfc2d46
5
5
  SHA512:
6
- metadata.gz: ea801613572d4ccdce2af524303220eed9f50532ce80160c8fd9063bb994f0be725cf806d84aad8ea2bf5028f593a79fa13b5d1f7e796ece29eee70d42df9fa8
7
- data.tar.gz: 9344d31ec8ffacdaa531a7e8bb7292270b151ad440d9dd95cd7ebfbe4106ca6b276ec3cff671df2ad97c9aee50892d453b584f948a7fc5e1bf7710fd935b2d40
6
+ metadata.gz: 9c154d015c820d314a4f2b7e7b611d4d858c75950bdef0fbde8d89b7264271b85a43669607e274ea1eca46234e603d48a441fb7a291b6a1969f8c5fb3896bf86
7
+ data.tar.gz: 5d9534cc68b264fe3901f447383de0265d301ddea893b435b39542575f2b16410569a4442ddb5a5187e803546cf721e3cf1e49a1f81a3c4439f59c4b46b42249
data/CHANGELOG.md CHANGED
@@ -1,5 +1,66 @@
1
1
  # Changelog
2
2
 
3
+ ## [v2.9.6](https://github.com/bensheldon/good_job/tree/v2.9.6) (2022-02-07)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.9.5...v2.9.6)
6
+
7
+ **Merged pull requests:**
8
+
9
+ - Limit query for allowed concurrent jobs to unfinished [\#515](https://github.com/bensheldon/good_job/pull/515) ([til](https://github.com/til))
10
+
11
+ ## [v2.9.5](https://github.com/bensheldon/good_job/tree/v2.9.5) (2022-02-07)
12
+
13
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.9.4...v2.9.5)
14
+
15
+ **Fixed bugs:**
16
+
17
+ - Transactions in "aborting" threads do not commit; causes GoodJob::Process record not destroyed on exit [\#489](https://github.com/bensheldon/good_job/issues/489)
18
+ - Deserialize ActiveJob arguments when manually retrying a job [\#513](https://github.com/bensheldon/good_job/pull/513) ([bensheldon](https://github.com/bensheldon))
19
+
20
+ **Closed issues:**
21
+
22
+ - Concurrency key proc is missing `arguments` when retrying a discarded job. [\#512](https://github.com/bensheldon/good_job/issues/512)
23
+ - Cron Schedule not visible in dashboard [\#496](https://github.com/bensheldon/good_job/issues/496)
24
+
25
+ **Merged pull requests:**
26
+
27
+ - Rename methods to `advisory_lock_key` and allow it to take a block instead of `with_advisory_lock` [\#511](https://github.com/bensheldon/good_job/pull/511) ([bensheldon](https://github.com/bensheldon))
28
+ - README: Limiting concurrency - fetch symbol instead of string [\#510](https://github.com/bensheldon/good_job/pull/510) ([BenSto](https://github.com/BenSto))
29
+ - Add arbitrary lock on class level too [\#499](https://github.com/bensheldon/good_job/pull/499) ([pandwoter](https://github.com/pandwoter))
30
+
31
+ ## [v2.9.4](https://github.com/bensheldon/good_job/tree/v2.9.4) (2022-01-31)
32
+
33
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.9.3...v2.9.4)
34
+
35
+ **Fixed bugs:**
36
+
37
+ - Fix navbar toggler [\#506](https://github.com/bensheldon/good_job/pull/506) ([JuanVqz](https://github.com/JuanVqz))
38
+ - Guard LogSubscriber against tagged logger without a formatter [\#504](https://github.com/bensheldon/good_job/pull/504) ([bensheldon](https://github.com/bensheldon))
39
+ - Markdown lint fixes + Added missing responsive meta tag [\#492](https://github.com/bensheldon/good_job/pull/492) ([zeevy](https://github.com/zeevy))
40
+
41
+ **Closed issues:**
42
+
43
+ - The navbar icon doesn't show the navbar menu when clicking it [\#503](https://github.com/bensheldon/good_job/issues/503)
44
+ - Not all loggers have a formatter [\#502](https://github.com/bensheldon/good_job/issues/502)
45
+ - Error logs from failed jobs used all storage space [\#495](https://github.com/bensheldon/good_job/issues/495)
46
+
47
+ **Merged pull requests:**
48
+
49
+ - Update Code of Conduct to Contributor Covenant 2.1 [\#501](https://github.com/bensheldon/good_job/pull/501) ([bensheldon](https://github.com/bensheldon))
50
+ - Test with Ruby 3.1 [\#498](https://github.com/bensheldon/good_job/pull/498) ([aried3r](https://github.com/aried3r))
51
+
52
+ ## [v2.9.3](https://github.com/bensheldon/good_job/tree/v2.9.3) (2022-01-23)
53
+
54
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.9.2...v2.9.3)
55
+
56
+ **Fixed bugs:**
57
+
58
+ - Use `*_url` route helpers for Dashboard assets to avoid being overridden by `config.asset_host` [\#493](https://github.com/bensheldon/good_job/pull/493) ([bensheldon](https://github.com/bensheldon))
59
+
60
+ **Closed issues:**
61
+
62
+ - Assets not loaded when Rails is configured with a different hostname for assets [\#491](https://github.com/bensheldon/good_job/issues/491)
63
+
3
64
  ## [v2.9.2](https://github.com/bensheldon/good_job/tree/v2.9.2) (2022-01-19)
4
65
 
5
66
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.9.1...v2.9.2)
data/README.md CHANGED
@@ -119,7 +119,7 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
119
119
  - By default, GoodJob separates job enqueuing from job execution so that jobs can be scaled independently of the web server. Use the GoodJob command-line tool to execute jobs:
120
120
 
121
121
  ```bash
122
- $ bundle exec good_job start
122
+ bundle exec good_job start
123
123
  ```
124
124
 
125
125
  Ideally the command-line tool should be run on a separate machine or container from the web process. For example, on Heroku:
@@ -133,8 +133,8 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
133
133
 
134
134
  - GoodJob can also be configured to execute jobs within the web server process to save on resources. This is useful for low-workloads when economy is paramount.
135
135
 
136
- ```
137
- $ GOOD_JOB_EXECUTION_MODE=async rails server
136
+ ```bash
137
+ GOOD_JOB_EXECUTION_MODE=async rails server
138
138
  ```
139
139
 
140
140
  Additional configuration is likely necessary, see the reference below for configuration.
@@ -399,11 +399,9 @@ class MyJob < ApplicationJob
399
399
 
400
400
  # A unique key to be globally locked against.
401
401
  # Can be String or Lambda/Proc that is invoked in the context of the job.
402
- # Note: Arguments passed to #perform_later must be accessed through `arguments` method.
403
- key: -> { "Unique-#{arguments.first}" } # MyJob.perform_later("Alice") => "Unique-Alice"
404
-
405
- # If the method uses named parameters, they can be accessed like so:
406
- # key: -> { "Unique-#{arguments.first['name']}" } # MyJob.perform_later(name: "Alice")
402
+ # Note: Arguments passed to #perform_later can be accessed through ActiveJob's `arguments` method
403
+ # which is an array containing positional arguments and, optionally, a kwarg hash.
404
+ key: -> { "Unique-#{arguments.first}-#{arguments.last[:version]}" } # MyJob.perform_later("Alice", version: 'v2') => "Unique-Alice-v2"
407
405
  )
408
406
 
409
407
  def perform(first_name)
@@ -470,7 +468,7 @@ To perform upgrades to the GoodJob database tables:
470
468
  Optional: If using Rails' multiple databases with the `migrations_paths` configuration option, use the `--database` option:
471
469
 
472
470
  ```bash
473
- $ bin/rails g good_job:update --database animals
471
+ bin/rails g good_job:update --database animals
474
472
  ```
475
473
 
476
474
  1. Run the database migration locally
@@ -703,7 +701,7 @@ GoodJob can execute jobs "async" in the same process as the web server (e.g. `bi
703
701
  - Or, with environment variables:
704
702
 
705
703
  ```bash
706
- $ GOOD_JOB_EXECUTION_MODE=async GOOD_JOB_MAX_THREADS=4 GOOD_JOB_POLL_INTERVAL=30 bin/rails server
704
+ GOOD_JOB_EXECUTION_MODE=async GOOD_JOB_MAX_THREADS=4 GOOD_JOB_POLL_INTERVAL=30 bin/rails server
707
705
  ```
708
706
 
709
707
  Depending on your application configuration, you may need to take additional steps:
@@ -821,7 +819,7 @@ It is also necessary to delete these preserved jobs from the database after a ce
821
819
  - For example, using the `good_job` command-line utility:
822
820
 
823
821
  ```bash
824
- $ bundle exec good_job cleanup_preserved_jobs --before-seconds-ago=86400
822
+ bundle exec good_job cleanup_preserved_jobs --before-seconds-ago=86400
825
823
  ```
826
824
 
827
825
  ### PgBouncer compatibility
@@ -2,23 +2,26 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <title>Good Job Dashboard</title>
5
+ <meta charset="utf-8">
6
+ <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
5
7
  <%= csrf_meta_tags %>
6
8
  <%= csp_meta_tag %>
7
9
 
8
- <%= stylesheet_link_tag bootstrap_path(format: :css, v: GoodJob::VERSION) %>
9
- <%= stylesheet_link_tag style_path(format: :css, v: GoodJob::VERSION) %>
10
+ <%# Assets must use *_url route helpers to avoid being overriden by config.asset_host %>
11
+ <%= stylesheet_link_tag bootstrap_url(format: :css, v: GoodJob::VERSION), skip_pipeline: true %>
12
+ <%= stylesheet_link_tag style_url(format: :css, v: GoodJob::VERSION) %>
10
13
 
11
- <%= javascript_include_tag bootstrap_path(format: :js, v: GoodJob::VERSION), nonce: true %>
12
- <%= javascript_include_tag chartjs_path(format: :js, v: GoodJob::VERSION), nonce: true %>
13
- <%= javascript_include_tag scripts_path(format: :js, v: GoodJob::VERSION), nonce: true %>
14
+ <%= javascript_include_tag bootstrap_url(format: :js, v: GoodJob::VERSION), nonce: true %>
15
+ <%= javascript_include_tag chartjs_url(format: :js, v: GoodJob::VERSION), nonce: true %>
16
+ <%= javascript_include_tag scripts_url(format: :js, v: GoodJob::VERSION), nonce: true %>
14
17
 
15
- <%= javascript_include_tag rails_ujs_path(format: :js, v: GoodJob::VERSION), nonce: true %>
18
+ <%= javascript_include_tag rails_ujs_url(format: :js, v: GoodJob::VERSION), nonce: true %>
16
19
  </head>
17
20
  <body>
18
21
  <nav class="navbar navbar-expand-lg navbar-light bg-light">
19
22
  <div class="container-fluid">
20
23
  <%= link_to "GoodJob 👍", root_path, class: 'navbar-brand mb-0 h1' %>
21
- <button class="navbar-toggler" type="button" data-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
24
+ <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
22
25
  <span class="navbar-toggler-icon"></span>
23
26
  </button>
24
27
 
@@ -30,7 +30,7 @@ module GoodJob
30
30
  key = job.good_job_concurrency_key
31
31
  next(block.call) if key.blank?
32
32
 
33
- GoodJob::Execution.new.with_advisory_lock(key: key, function: "pg_advisory_lock") do
33
+ GoodJob::Execution.advisory_lock_key(key, function: "pg_advisory_lock") do
34
34
  enqueue_concurrency = if enqueue_limit
35
35
  GoodJob::Execution.where(concurrency_key: key).unfinished.advisory_unlocked.count
36
36
  else
@@ -61,8 +61,8 @@ module GoodJob
61
61
  key = job.good_job_concurrency_key
62
62
  next if key.blank?
63
63
 
64
- GoodJob::Execution.new.with_advisory_lock(key: key, function: "pg_advisory_lock") do
65
- allowed_active_job_ids = GoodJob::Execution.where(concurrency_key: key).advisory_locked.order(Arel.sql("COALESCE(performed_at, scheduled_at, created_at) ASC")).limit(perform_limit).pluck(:active_job_id)
64
+ GoodJob::Execution.advisory_lock_key(key, function: "pg_advisory_lock") do
65
+ allowed_active_job_ids = GoodJob::Execution.unfinished.where(concurrency_key: key).advisory_locked.order(Arel.sql("COALESCE(performed_at, scheduled_at, created_at) ASC")).limit(perform_limit).pluck(:active_job_id)
66
66
  # The current job has already been locked and will appear in the previous query
67
67
  raise GoodJob::ActiveJobExtensions::Concurrency::ConcurrencyExceededError unless allowed_active_job_ids.include? job.job_id
68
68
  end
@@ -267,7 +267,9 @@ module GoodJob
267
267
  end
268
268
 
269
269
  def active_job
270
- ActiveJob::Base.deserialize(active_job_data)
270
+ ActiveJob::Base.deserialize(active_job_data).tap do |aj|
271
+ aj.send(:deserialize_arguments_if_needed)
272
+ end
271
273
  end
272
274
 
273
275
  private
@@ -148,6 +148,7 @@ module GoodJob
148
148
  raise ArgumentError, "Must provide a block" unless block_given?
149
149
 
150
150
  records = advisory_lock(column: column, function: function).to_a
151
+
151
152
  begin
152
153
  unscoped { yield(records) }
153
154
  ensure
@@ -161,6 +162,53 @@ module GoodJob
161
162
  end
162
163
  end
163
164
 
165
+ # Acquires an advisory lock on this record if it is not already locked by
166
+ # another database session. Be careful to ensure you release the lock when
167
+ # you are done with {#advisory_unlock_key} to release all remaining locks.
168
+ # @param key [String, Symbol] Key to Advisory Lock against
169
+ # @param function [String, Symbol] Postgres Advisory Lock function name to use
170
+ # @return [Boolean] whether the lock was acquired.
171
+ def advisory_lock_key(key, function: advisory_lockable_function)
172
+ query = if function.include? "_try_"
173
+ <<~SQL.squish
174
+ SELECT #{function}(('x'||substr(md5($1::text), 1, 16))::bit(64)::bigint) AS locked
175
+ SQL
176
+ else
177
+ <<~SQL.squish
178
+ SELECT #{function}(('x'||substr(md5($1::text), 1, 16))::bit(64)::bigint)::text AS locked
179
+ SQL
180
+ end
181
+
182
+ binds = [
183
+ ActiveRecord::Relation::QueryAttribute.new('key', key, ActiveRecord::Type::String.new),
184
+ ]
185
+ locked = connection.exec_query(pg_or_jdbc_query(query), 'GoodJob::Lockable Advisory Lock', binds).first['locked']
186
+ return locked unless block_given?
187
+ return nil unless locked
188
+
189
+ begin
190
+ yield
191
+ ensure
192
+ advisory_unlock_key(key, function: advisory_unlockable_function(function))
193
+ end
194
+ end
195
+
196
+ # Releases an advisory lock on this record if it is locked by this database
197
+ # session. Note that advisory locks stack, so you must call
198
+ # {#advisory_unlock} and {#advisory_lock} the same number of times.
199
+ # @param key [String, Symbol] Key to lock against
200
+ # @param function [String, Symbol] Postgres Advisory Lock function name to use
201
+ # @return [Boolean] whether the lock was released.
202
+ def advisory_unlock_key(key, function: advisory_unlockable_function)
203
+ query = <<~SQL.squish
204
+ SELECT #{function}(('x'||substr(md5($1::text), 1, 16))::bit(64)::bigint) AS unlocked
205
+ SQL
206
+ binds = [
207
+ ActiveRecord::Relation::QueryAttribute.new('key', key, ActiveRecord::Type::String.new),
208
+ ]
209
+ connection.exec_query(pg_or_jdbc_query(query), 'GoodJob::Lockable Advisory Unlock', binds).first['unlocked']
210
+ end
211
+
164
212
  def _advisory_lockable_column
165
213
  advisory_lockable_column || primary_key
166
214
  end
@@ -205,20 +253,7 @@ module GoodJob
205
253
  # @param function [String, Symbol] Postgres Advisory Lock function name to use
206
254
  # @return [Boolean] whether the lock was acquired.
207
255
  def advisory_lock(key: lockable_key, function: advisory_lockable_function)
208
- query = if function.include? "_try_"
209
- <<~SQL.squish
210
- SELECT #{function}(('x'||substr(md5($1::text), 1, 16))::bit(64)::bigint) AS locked
211
- SQL
212
- else
213
- <<~SQL.squish
214
- SELECT #{function}(('x'||substr(md5($1::text), 1, 16))::bit(64)::bigint)::text AS locked
215
- SQL
216
- end
217
-
218
- binds = [
219
- ActiveRecord::Relation::QueryAttribute.new('key', key, ActiveRecord::Type::String.new),
220
- ]
221
- self.class.connection.exec_query(pg_or_jdbc_query(query), 'GoodJob::Lockable Advisory Lock', binds).first['locked']
256
+ self.class.advisory_lock_key(key, function: function)
222
257
  end
223
258
 
224
259
  # Releases an advisory lock on this record if it is locked by this database
@@ -228,13 +263,7 @@ module GoodJob
228
263
  # @param function [String, Symbol] Postgres Advisory Lock function name to use
229
264
  # @return [Boolean] whether the lock was released.
230
265
  def advisory_unlock(key: lockable_key, function: self.class.advisory_unlockable_function(advisory_lockable_function))
231
- query = <<~SQL.squish
232
- SELECT #{function}(('x'||substr(md5($1::text), 1, 16))::bit(64)::bigint) AS unlocked
233
- SQL
234
- binds = [
235
- ActiveRecord::Relation::QueryAttribute.new('key', key, ActiveRecord::Type::String.new),
236
- ]
237
- self.class.connection.exec_query(pg_or_jdbc_query(query), 'GoodJob::Lockable Advisory Unlock', binds).first['unlocked']
266
+ self.class.advisory_unlock_key(key, function: function)
238
267
  end
239
268
 
240
269
  # Acquires an advisory lock on this record or raises
@@ -245,8 +274,7 @@ module GoodJob
245
274
  # @raise [RecordAlreadyAdvisoryLockedError]
246
275
  # @return [Boolean] +true+
247
276
  def advisory_lock!(key: lockable_key, function: advisory_lockable_function)
248
- result = advisory_lock(key: key, function: function)
249
- result || raise(RecordAlreadyAdvisoryLockedError)
277
+ self.class.advisory_lock_key(key, function: function) || raise(RecordAlreadyAdvisoryLockedError)
250
278
  end
251
279
 
252
280
  # Acquires an advisory lock on this record and safely releases it after the
@@ -266,9 +294,11 @@ module GoodJob
266
294
  raise ArgumentError, "Must provide a block" unless block_given?
267
295
 
268
296
  advisory_lock!(key: key, function: function)
269
- yield
270
- ensure
271
- advisory_unlock(key: key, function: self.class.advisory_unlockable_function(function)) unless $ERROR_INFO.is_a? RecordAlreadyAdvisoryLockedError
297
+ begin
298
+ yield
299
+ ensure
300
+ advisory_unlock(key: key, function: self.class.advisory_unlockable_function(function))
301
+ end
272
302
  end
273
303
 
274
304
  # Tests whether this record has an advisory lock on it.
@@ -206,7 +206,7 @@ module GoodJob
206
206
  good_job_tag = ["ActiveJob"].freeze
207
207
 
208
208
  self.class.loggers.inject(block) do |inner, each_logger|
209
- if each_logger.respond_to?(:tagged)
209
+ if each_logger.respond_to?(:tagged) && each_logger.formatter
210
210
  tags_for_logger = if each_logger.formatter.current_tags.include?("ActiveJob")
211
211
  good_job_tag + tags
212
212
  else
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module GoodJob
3
3
  # GoodJob gem version.
4
- VERSION = '2.9.2'
4
+ VERSION = '2.9.6'
5
5
  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: 2.9.2
4
+ version: 2.9.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: 2022-01-19 00:00:00.000000000 Z
11
+ date: 2022-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob