good_job 2.8.1 → 2.9.3

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: bca3de7432f33744351456a803dcbb74f73c0228f824dad035b51565c711e529
4
- data.tar.gz: 0e0b3d2959f2db50c00d61a49ccad52be73711ac8e07cfd7cfffb186923fb5b2
3
+ metadata.gz: 815933ed8a435e9826bbb655e92c298d10d5bd74eb4f0474cb25d49a194d5cae
4
+ data.tar.gz: 29f7753f2401599feb16fc4b25e9c7073855f1fa135d88e640051533c2c24593
5
5
  SHA512:
6
- metadata.gz: ad760ae64fe74a08943013b9359e675bf46ad366cb9a688937a182e2fc8b6abd336fa8b8408cc61e22cf7c3ab713d0fa9e0a6ae973196d653e5c763818ef1672
7
- data.tar.gz: 630f2765587b5b675eaf1e33b6c5b39a83ada8980a0638011e2cc71f4ce963d6f6287db5d50a9c5efb3d1ba7c1402e7ef1f2beb11369ad981a6046c8e4491f30
6
+ metadata.gz: 7dbf7489f53095634bb91e2a7e7fd8bb1a009ba3d81fb98312c7b8ae8f0516bc786e13b1100fdef1dd113e80c59b3d8433663ea4773d04ee517927f1bce1b560
7
+ data.tar.gz: b01d4ca76bb300dd4f755db2eb43758dd8146fe4e4ab1061d47cc973fe8e559b936df004054ed9ed92c9aefc6abee8f7db0ab33bf1ca812b57a9d7c192771077
data/CHANGELOG.md CHANGED
@@ -1,5 +1,57 @@
1
1
  # Changelog
2
2
 
3
+ ## [v2.9.3](https://github.com/bensheldon/good_job/tree/v2.9.3) (2022-01-23)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.9.2...v2.9.3)
6
+
7
+ **Closed issues:**
8
+
9
+ - Assets not loaded when Rails is configured with a different hostname for assets [\#491](https://github.com/bensheldon/good_job/issues/491)
10
+
11
+ **Merged pull requests:**
12
+
13
+ - 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))
14
+
15
+ ## [v2.9.2](https://github.com/bensheldon/good_job/tree/v2.9.2) (2022-01-19)
16
+
17
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.9.1...v2.9.2)
18
+
19
+ **Fixed bugs:**
20
+
21
+ - Error on GJ admin UI search form [\#487](https://github.com/bensheldon/good_job/issues/487)
22
+ - Use `websearch_to_tsquery` or \(`plainto_tsquery` for Postgres \< v11\) for Dashboard search filter [\#488](https://github.com/bensheldon/good_job/pull/488) ([bensheldon](https://github.com/bensheldon))
23
+
24
+ **Merged pull requests:**
25
+
26
+ - Update README to illustrate using named arguments for the unique key. [\#486](https://github.com/bensheldon/good_job/pull/486) ([phallstrom](https://github.com/phallstrom))
27
+ - Add details about exactly where to require the engine. [\#485](https://github.com/bensheldon/good_job/pull/485) ([phallstrom](https://github.com/phallstrom))
28
+ - $ symbol gets copied when clicking on the copy button [\#484](https://github.com/bensheldon/good_job/pull/484) ([zeevy](https://github.com/zeevy))
29
+
30
+ ## [v2.9.1](https://github.com/bensheldon/good_job/tree/v2.9.1) (2022-01-13)
31
+
32
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.9.0...v2.9.1)
33
+
34
+ **Fixed bugs:**
35
+
36
+ - Start async adapters once `ActiveRecord` and `ActiveJob` have loaded, potentially before `Rails.application.initialized?` [\#483](https://github.com/bensheldon/good_job/pull/483) ([bensheldon](https://github.com/bensheldon))
37
+
38
+ **Closed issues:**
39
+
40
+ - Graceful fallback to polling when LISTEN/NOTIFY isn't available [\#482](https://github.com/bensheldon/good_job/issues/482)
41
+ - Long running locks on latest good job [\#480](https://github.com/bensheldon/good_job/issues/480)
42
+
43
+ ## [v2.9.0](https://github.com/bensheldon/good_job/tree/v2.9.0) (2022-01-09)
44
+
45
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.8.1...v2.9.0)
46
+
47
+ **Implemented enhancements:**
48
+
49
+ - Add JRuby / JDBC support for LISTEN [\#479](https://github.com/bensheldon/good_job/pull/479) ([bensheldon](https://github.com/bensheldon))
50
+
51
+ **Merged pull requests:**
52
+
53
+ - Remove demo CleanupJob in favor of using built-in cleanup intervals [\#478](https://github.com/bensheldon/good_job/pull/478) ([bensheldon](https://github.com/bensheldon))
54
+
3
55
  ## [v2.8.1](https://github.com/bensheldon/good_job/tree/v2.8.1) (2022-01-03)
4
56
 
5
57
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.8.0...v2.8.1)
data/README.md CHANGED
@@ -73,19 +73,19 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
73
73
  1. Install the gem:
74
74
 
75
75
  ```bash
76
- $ bundle install
76
+ bundle install
77
77
  ```
78
78
 
79
79
  1. Run the GoodJob install generator. This will generate a database migration to create a table for GoodJob's job records:
80
80
 
81
81
  ```bash
82
- $ bin/rails g good_job:install
82
+ bin/rails g good_job:install
83
83
  ```
84
84
 
85
85
  Run the migration:
86
86
 
87
87
  ```bash
88
- $ bin/rails db:migrate
88
+ bin/rails db:migrate
89
89
  ```
90
90
 
91
91
  Optional: If using Rails' multiple databases with the `migrations_paths` configuration option, use the `--database` option:
@@ -142,7 +142,7 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
142
142
  ## Compatibility
143
143
 
144
144
  - **Ruby on Rails:** 5.2+
145
- - **Ruby:** MRI 2.5+. JRuby 9.2.13+ (_JRuby's `activerecord-jdbcpostgresql-adapter` gem does not support Postgres LISTEN/NOTIFY)._
145
+ - **Ruby:** MRI 2.5+. JRuby 9.2.13+
146
146
  - **Postgres:** 9.6+
147
147
 
148
148
  ## Configuration
@@ -328,7 +328,7 @@ _🚧 GoodJob's dashboard is a work in progress. Please contribute ideas and cod
328
328
 
329
329
  GoodJob includes a Dashboard as a mountable `Rails::Engine`.
330
330
 
331
- 1. Explicitly require the Engine code at the top of your `config/application.rb` file, immediately after Rails is required. This is necessary because the mountable engine is an optional feature of GoodJob.
331
+ 1. Explicitly require the Engine code at the top of your `config/application.rb` file, immediately after Rails is required and before Bundler requires the Rails' groups. This is necessary because the mountable engine is an optional feature of GoodJob.
332
332
 
333
333
  ```ruby
334
334
  # config/application.rb
@@ -339,6 +339,8 @@ GoodJob includes a Dashboard as a mountable `Rails::Engine`.
339
339
  # ...
340
340
  ```
341
341
 
342
+ Note: If you find the dashboard fails to reload due to a routing error and uninitialized constant `GoodJob::ExecutionsController`, this is likely because you are not requiring the engine early enough.
343
+
342
344
  1. Mount the engine in your `config/routes.rb` file. The following will mount it at `http://example.com/good_job`.
343
345
 
344
346
  ```ruby
@@ -399,6 +401,9 @@ class MyJob < ApplicationJob
399
401
  # Can be String or Lambda/Proc that is invoked in the context of the job.
400
402
  # Note: Arguments passed to #perform_later must be accessed through `arguments` method.
401
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
407
  )
403
408
 
404
409
  def perform(first_name)
@@ -5,14 +5,15 @@
5
5
  <%= csrf_meta_tags %>
6
6
  <%= csp_meta_tag %>
7
7
 
8
- <%= stylesheet_link_tag bootstrap_path(format: :css, v: GoodJob::VERSION) %>
9
- <%= stylesheet_link_tag style_path(format: :css, v: GoodJob::VERSION) %>
8
+ <%# Assets must use *_url route helpers to avoid being overriden by config.asset_host %>
9
+ <%= stylesheet_link_tag bootstrap_url(format: :css, v: GoodJob::VERSION), skip_pipeline: true %>
10
+ <%= stylesheet_link_tag style_url(format: :css, v: GoodJob::VERSION) %>
10
11
 
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 %>
12
+ <%= javascript_include_tag bootstrap_url(format: :js, v: GoodJob::VERSION), nonce: true %>
13
+ <%= javascript_include_tag chartjs_url(format: :js, v: GoodJob::VERSION), nonce: true %>
14
+ <%= javascript_include_tag scripts_url(format: :js, v: GoodJob::VERSION), nonce: true %>
14
15
 
15
- <%= javascript_include_tag rails_ujs_path(format: :js, v: GoodJob::VERSION), nonce: true %>
16
+ <%= javascript_include_tag rails_ujs_url(format: :js, v: GoodJob::VERSION), nonce: true %>
16
17
  </head>
17
18
  <body>
18
19
  <nav class="navbar navbar-expand-lg navbar-light bg-light">
@@ -27,7 +27,7 @@ module GoodJob
27
27
  # @param queues [String, nil] determines which queues to execute jobs from when +execution_mode+ is set to +:async+. See {file:README.md#optimize-queues-threads-and-processes} for more details on the format of this string. You can also set this with the environment variable +GOOD_JOB_QUEUES+. Defaults to +"*"+.
28
28
  # @param poll_interval [Integer, nil] sets the number of seconds between polls for jobs when +execution_mode+ is set to +:async+. You can also set this with the environment variable +GOOD_JOB_POLL_INTERVAL+. Defaults to +1+.
29
29
  # @param start_async_on_initialize [Boolean] whether to start the async scheduler when the adapter is initialized.
30
- def initialize(execution_mode: nil, queues: nil, max_threads: nil, poll_interval: nil, start_async_on_initialize: Rails.application.initialized?)
30
+ def initialize(execution_mode: nil, queues: nil, max_threads: nil, poll_interval: nil, start_async_on_initialize: GoodJob.async_ready?)
31
31
  @configuration = GoodJob::Configuration.new(
32
32
  {
33
33
  execution_mode: execution_mode,
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GoodJob # :nodoc:
4
+ # Extends GoodJob module to track Rails boot dependencies.
5
+ module Dependencies
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ # @!attribute [rw] _rails_after_initialize_hook_called
10
+ # @!scope class
11
+ # Whether Railtie.after_initialize has been called yet (default: +false+).
12
+ # This will be set on but before +Rails.application.initialize?+ is +true+.
13
+ # @return [Boolean]
14
+ mattr_accessor :_rails_after_initialize_hook_called, default: false
15
+
16
+ # @!attribute [rw] _active_job_loaded
17
+ # @!scope class
18
+ # Whether ActiveJob has loaded (default: +false+).
19
+ # @return [Boolean]
20
+ mattr_accessor :_active_job_loaded, default: false
21
+
22
+ # @!attribute [rw] _active_record_loaded
23
+ # @!scope class
24
+ # Whether ActiveRecord has loaded (default: +false+).
25
+ # @return [Boolean]
26
+ mattr_accessor :_active_record_loaded, default: false
27
+ end
28
+
29
+ class_methods do
30
+ # Whether GoodJob's has been initialized as of the calling of +Railtie.after_initialize+.
31
+ # @return [Boolean]
32
+ def async_ready?
33
+ Rails.application.initialized? || (
34
+ _rails_after_initialize_hook_called &&
35
+ _active_job_loaded &&
36
+ _active_record_loaded
37
+ )
38
+ end
39
+
40
+ def start_async_adapters
41
+ return unless async_ready?
42
+
43
+ GoodJob::Adapter.instances
44
+ .select(&:execute_async?)
45
+ .reject(&:async_started?)
46
+ .each(&:start_async)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -34,9 +34,18 @@ module GoodJob
34
34
  next if query.blank?
35
35
 
36
36
  tsvector = "(to_tsvector('english', serialized_params) || to_tsvector('english', id::text) || to_tsvector('english', COALESCE(error, '')::text))"
37
- where("#{tsvector} @@ to_tsquery(?)", query)
38
- .order(sanitize_sql_for_order([Arel.sql("ts_rank(#{tsvector}, to_tsquery(?))"), query]) => 'DESC')
37
+ to_tsquery_function = database_supports_websearch_to_tsquery? ? 'websearch_to_tsquery' : 'plainto_tsquery'
38
+ where("#{tsvector} @@ #{to_tsquery_function}(?)", query)
39
+ .order(sanitize_sql_for_order([Arel.sql("ts_rank(#{tsvector}, #{to_tsquery_function}(?))"), query]) => 'DESC')
39
40
  end)
40
41
  end
42
+
43
+ class_methods do
44
+ def database_supports_websearch_to_tsquery?
45
+ return @_database_supports_websearch_to_tsquery if defined?(@_database_supports_websearch_to_tsquery)
46
+
47
+ @_database_supports_websearch_to_tsquery = connection.postgresql_version >= 110000
48
+ end
49
+ end
41
50
  end
42
51
  end
@@ -16,9 +16,6 @@ module GoodJob # :nodoc:
16
16
 
17
17
  include Notifier::ProcessRegistration
18
18
 
19
- # Raised if the Database adapter does not implement LISTEN.
20
- AdapterCannotListenError = Class.new(StandardError)
21
-
22
19
  # Default Postgres channel for LISTEN/NOTIFY
23
20
  CHANNEL = 'good_job'
24
21
  # Defaults for instance of Concurrent::ThreadPoolExecutor
@@ -129,8 +126,6 @@ module GoodJob # :nodoc:
129
126
  # @!visibility private
130
127
  # @return [void]
131
128
  def listen_observer(_time, _result, thread_error)
132
- return if thread_error.is_a? AdapterCannotListenError
133
-
134
129
  if thread_error
135
130
  GoodJob._on_thread_error(thread_error)
136
131
  ActiveSupport::Notifications.instrument("notifier_notify_error.good_job", { error: thread_error })
@@ -214,6 +209,15 @@ module GoodJob # :nodoc:
214
209
  raw_connection.wait_for_notify(WAIT_INTERVAL) do |channel, _pid, payload|
215
210
  yield(channel, payload)
216
211
  end
212
+ elsif raw_connection.respond_to?(:jdbc_connection)
213
+ raw_connection.execute_query("SELECT 1")
214
+ notifications = raw_connection.jdbc_connection.getNotifications
215
+ Array(notifications).each do |notification|
216
+ channel = notification.getName
217
+ payload = notification.getParameter
218
+ yield(channel, payload)
219
+ end
220
+ sleep WAIT_INTERVAL
217
221
  else
218
222
  sleep WAIT_INTERVAL
219
223
  end
@@ -34,8 +34,27 @@ module GoodJob
34
34
  end
35
35
 
36
36
  initializer "good_job.start_async" do
37
+ # This hooks into the hookable places during Rails boot, which is unfortunately not Rails.application.initialized?
38
+ # If an Adapter is initialized during boot, we want to want to start its async executors once the framework dependencies have loaded.
39
+ # When exactly that happens is out of our control because gems or application code may touch things earlier than expected.
40
+ # For example, as of Rails 6.1, if an ActiveRecord model is touched during boot, that triggers ActiveRecord to load,
41
+ # which touches DestroyAssociationAsyncJob, which loads ActiveJob, which may initialize a GoodJob::Adapter, all of which
42
+ # happens _before_ ActiveRecord finishes loading. GoodJob will deadlock if an async executor is started in the middle of
43
+ # ActiveRecord loading.
44
+
37
45
  config.after_initialize do
38
- GoodJob::Adapter.instances.each(&:start_async)
46
+ ActiveSupport.on_load(:active_record) do
47
+ GoodJob._active_record_loaded = true
48
+ GoodJob.start_async_adapters
49
+ end
50
+
51
+ ActiveSupport.on_load(:active_job) do
52
+ GoodJob._active_job_loaded = true
53
+ GoodJob.start_async_adapters
54
+ end
55
+
56
+ GoodJob._rails_after_initialize_hook_called = true
57
+ GoodJob.start_async_adapters
39
58
  end
40
59
  end
41
60
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module GoodJob
3
3
  # GoodJob gem version.
4
- VERSION = '2.8.1'
4
+ VERSION = '2.9.3'
5
5
  end
data/lib/good_job.rb CHANGED
@@ -18,6 +18,8 @@ require "good_job/railtie"
18
18
  #
19
19
  # +GoodJob+ is the top-level namespace and exposes configuration attributes.
20
20
  module GoodJob
21
+ include GoodJob::Dependencies
22
+
21
23
  DEFAULT_LOGGER = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new($stdout))
22
24
 
23
25
  # @!attribute [rw] active_record_parent_class
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.8.1
4
+ version: 2.9.3
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-03 00:00:00.000000000 Z
11
+ date: 2022-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -421,6 +421,7 @@ files:
421
421
  - lib/good_job/cron_manager.rb
422
422
  - lib/good_job/current_thread.rb
423
423
  - lib/good_job/daemon.rb
424
+ - lib/good_job/dependencies.rb
424
425
  - lib/good_job/execution.rb
425
426
  - lib/good_job/execution_result.rb
426
427
  - lib/good_job/filterable.rb