good_job 2.8.1 → 2.9.3

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: 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