good_job 1.9.3 → 1.9.4

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: 94f031dce3515297d2fa26803582e006a5787a681e3e2e7d50da00acea09cc27
4
- data.tar.gz: 4fb166ced6dc815a3784a98d8ec2ae80d3ba843783435c035fadf577c83192a7
3
+ metadata.gz: '039fb246e970dd21bfa88b72a50fd96038c00bd4dd0c323966936a9899ade684'
4
+ data.tar.gz: bb19f26989f503ce572759c7726b07ee56208b0defc793de6e0ca07c500cb869
5
5
  SHA512:
6
- metadata.gz: 294c5bc738d9cf2953be24c0e5e9b3a04890d4861fb75c6e6040bbd49d63da2abf953dac367f92173c49c4e032824d6547f4a6f005bf035086bbd624b2db8405
7
- data.tar.gz: c12d8e513db1e6c1976aa4e6478005d803f440f2cf75037fee389f111aa07303e539cdcc998a622f49571b78de84261503ee5e71e86b61702ea02bc82cd3e882
6
+ metadata.gz: 78516e648a709192486d728061d19850f108daa6863ec714b51ee1eb0e03c1ca7a6294d4736e70e8d657d34abfd8105168a94b26a2fe7ec33df0db4e04587574
7
+ data.tar.gz: 416b0b8fb14e082abefffd7d5a4ee7eea53725eeba4dd0d7786e6c8caaa833cb318a5205863ae6aa6e3d475e9abfd3aff687ccde2bc93b4b435764f614c8251a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.9.4](https://github.com/bensheldon/good_job/tree/v1.9.4) (2021-05-18)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.9.3...v1.9.4)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Add "running" jobs state to Dashboard [\#253](https://github.com/bensheldon/good_job/pull/253) ([morgoth](https://github.com/morgoth))
10
+
11
+ **Fixed bugs:**
12
+
13
+ - Unify displaying timestamps [\#252](https://github.com/bensheldon/good_job/pull/252) ([morgoth](https://github.com/morgoth))
14
+ - Fix dashboard jobs endless pagination with timezone handling [\#251](https://github.com/bensheldon/good_job/pull/251) ([morgoth](https://github.com/morgoth))
15
+
16
+ **Closed issues:**
17
+
18
+ - exception\_executions not counted correctly? [\#215](https://github.com/bensheldon/good_job/issues/215)
19
+ - Document issues with PgBouncer and session-level Advisory Locks [\#52](https://github.com/bensheldon/good_job/issues/52)
20
+
21
+ **Merged pull requests:**
22
+
23
+ - Add handy scope for filtering by job class [\#259](https://github.com/bensheldon/good_job/pull/259) ([morgoth](https://github.com/morgoth))
24
+ - Nest exception stub within job class and cleanup let! precedence to fix flakey JRuby tests [\#254](https://github.com/bensheldon/good_job/pull/254) ([bensheldon](https://github.com/bensheldon))
25
+ - Move good\_job\_spec.rb to proper location in lib directory [\#250](https://github.com/bensheldon/good_job/pull/250) ([bensheldon](https://github.com/bensheldon))
26
+ - Refactor deprecated wait parameter and assorted improvements [\#249](https://github.com/bensheldon/good_job/pull/249) ([bensheldon](https://github.com/bensheldon))
27
+ - Update development dependencies \(Rails v6.1.3.2\) [\#248](https://github.com/bensheldon/good_job/pull/248) ([bensheldon](https://github.com/bensheldon))
28
+ - Update YARD documentation param types and return values [\#239](https://github.com/bensheldon/good_job/pull/239) ([bensheldon](https://github.com/bensheldon))
29
+
3
30
  ## [v1.9.3](https://github.com/bensheldon/good_job/tree/v1.9.3) (2021-05-10)
4
31
 
5
32
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.9.2...v1.9.3)
@@ -10,7 +37,7 @@
10
37
 
11
38
  **Closed issues:**
12
39
 
13
- - Not processing unfinished jobs across server restarts using async\_server mode [\#244](https://github.com/bensheldon/good_job/issues/244)
40
+ - Not processing unfinished jobs across server restarts using async\_server mode on Iodine server [\#244](https://github.com/bensheldon/good_job/issues/244)
14
41
  - No connection pool for 'ActiveRecord::Base' found [\#236](https://github.com/bensheldon/good_job/issues/236)
15
42
 
16
43
  ## [v1.9.2](https://github.com/bensheldon/good_job/tree/v1.9.2) (2021-05-10)
@@ -12,17 +12,18 @@ module GoodJob
12
12
  end
13
13
 
14
14
  def jobs
15
- sql = GoodJob::Job.display_all(after_scheduled_at: params[:after_scheduled_at], after_id: params[:after_id])
15
+ after_scheduled_at = params[:after_scheduled_at].present? ? Time.zone.parse(params[:after_scheduled_at]) : nil
16
+ sql = GoodJob::Job.display_all(after_scheduled_at: after_scheduled_at, after_id: params[:after_id])
16
17
  .limit(params.fetch(:limit, 10))
17
- if params[:job_class] # rubocop:disable Style/IfUnlessModifier
18
- sql = sql.where("serialized_params->>'job_class' = ?", params[:job_class])
19
- end
18
+ sql = sql.with_job_class(params[:job_class]) if params[:job_class]
20
19
  if params[:state]
21
20
  case params[:state]
22
21
  when 'finished'
23
22
  sql = sql.finished
24
23
  when 'unfinished'
25
24
  sql = sql.unfinished
25
+ when 'running'
26
+ sql = sql.running
26
27
  when 'errors'
27
28
  sql = sql.where.not(error: nil)
28
29
  end
@@ -34,6 +35,7 @@ module GoodJob
34
35
  {
35
36
  'finished' => GoodJob::Job.finished.count,
36
37
  'unfinished' => GoodJob::Job.unfinished.count,
38
+ 'running' => GoodJob::Job.running.count,
37
39
  'errors' => GoodJob::Job.where.not(error: nil).count,
38
40
  }
39
41
  end
@@ -79,7 +81,7 @@ module GoodJob
79
81
  queue_names = job_data.map { |d| d['queue_name'] }.uniq
80
82
  labels = []
81
83
  queues_data = job_data.to_a.group_by { |d| d['timestamp'] }.each_with_object({}) do |(timestamp, values), hash|
82
- labels << timestamp
84
+ labels << timestamp.in_time_zone.to_s
83
85
  queue_names.each do |queue_name|
84
86
  (hash[queue_name] ||= []) << values.find { |d| d['queue_name'] == queue_name }&.[]('count')
85
87
  end
@@ -6,11 +6,12 @@
6
6
  fullWidth: true,
7
7
  chartPadding: {
8
8
  right: 40,
9
- top: 20
9
+ top: 20,
10
+ bottom: 20
10
11
  },
11
12
  axisX: {
12
13
  labelInterpolationFnc: function(value, index) {
13
- return index % 3 === 0 ? value : null;
14
+ return index % 3 === 0 ? value : null;
14
15
  }
15
16
  },
16
17
  axisY: {
data/lib/good_job.rb CHANGED
@@ -30,7 +30,7 @@ module GoodJob
30
30
  # @!scope class
31
31
  # The logger used by GoodJob (default: +Rails.logger+).
32
32
  # Use this to redirect logs to a special location or file.
33
- # @return [Logger]
33
+ # @return [Logger, nil]
34
34
  # @example Output GoodJob logs to a file:
35
35
  # GoodJob.logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new("log/my_logs.log"))
36
36
  mattr_accessor :logger, default: ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new($stdout))
@@ -42,7 +42,7 @@ module GoodJob
42
42
  # If you want to preserve jobs for latter inspection, set this to +true+.
43
43
  # If you want to preserve only jobs that finished with error for latter inspection, set this to +:on_unhandled_error+.
44
44
  # If +true+, you will need to clean out jobs using the +good_job cleanup_preserved_jobs+ CLI command.
45
- # @return [Boolean]
45
+ # @return [Boolean, nil]
46
46
  mattr_accessor :preserve_job_records, default: false
47
47
 
48
48
  # @!attribute [rw] retry_on_unhandled_error
@@ -51,10 +51,11 @@ module GoodJob
51
51
  # If +true+, causes jobs to be re-queued and retried if they raise an instance of +StandardError+.
52
52
  # If +false+, jobs will be discarded or marked as finished if they raise an instance of +StandardError+.
53
53
  # Instances of +Exception+, like +SIGINT+, will *always* be retried, regardless of this attribute's value.
54
- # @return [Boolean]
54
+ # @return [Boolean, nil]
55
55
  mattr_accessor :retry_on_unhandled_error, default: true
56
56
 
57
57
  # @deprecated Use {GoodJob#retry_on_unhandled_error} instead.
58
+ # @return [Boolean, nil]
58
59
  def self.reperform_jobs_on_standard_error
59
60
  ActiveSupport::Deprecation.warn(
60
61
  "Calling 'GoodJob.reperform_jobs_on_standard_error' is deprecated. Please use 'retry_on_unhandled_error'"
@@ -63,6 +64,8 @@ module GoodJob
63
64
  end
64
65
 
65
66
  # @deprecated Use {GoodJob#retry_on_unhandled_error=} instead.
67
+ # @param value [Boolean]
68
+ # @return [Boolean]
66
69
  def self.reperform_jobs_on_standard_error=(value)
67
70
  ActiveSupport::Deprecation.warn(
68
71
  "Setting 'GoodJob.reperform_jobs_on_standard_error=' is deprecated. Please use 'retry_on_unhandled_error='"
@@ -77,7 +80,7 @@ module GoodJob
77
80
  # @example Send errors to Sentry
78
81
  # # config/initializers/good_job.rb
79
82
  # GoodJob.on_thread_error = -> (exception) { Raven.capture_exception(exception) }
80
- # @return [#call, nil]
83
+ # @return [Proc, nil]
81
84
  mattr_accessor :on_thread_error, default: nil
82
85
 
83
86
  # Stop executing jobs.
@@ -93,13 +96,13 @@ module GoodJob
93
96
  # @param wait [Boolean] whether to wait for shutdown
94
97
  # @return [void]
95
98
  def self.shutdown(timeout: -1, wait: nil)
96
- timeout = if wait.present?
99
+ timeout = if wait.nil?
100
+ timeout
101
+ else
97
102
  ActiveSupport::Deprecation.warn(
98
103
  "Using `GoodJob.shutdown` with `wait:` kwarg is deprecated; use `timeout:` kwarg instead e.g. GoodJob.shutdown(timeout: #{wait ? '-1' : 'nil'})"
99
104
  )
100
105
  wait ? -1 : nil
101
- else
102
- timeout
103
106
  end
104
107
 
105
108
  executables = Array(Notifier.instances) + Array(Poller.instances) + Array(Scheduler.instances)
@@ -119,6 +122,7 @@ module GoodJob
119
122
  # When forking processes you should shut down these background threads before forking, and restart them after forking.
120
123
  # For example, you should use +shutdown+ and +restart+ when using async execution mode with Puma.
121
124
  # See the {file:README.md#executing-jobs-async--in-process} for more explanation and examples.
125
+ # @param timeout [Numeric, nil] Seconds to wait for active threads to finish.
122
126
  # @return [void]
123
127
  def self.restart(timeout: -1)
124
128
  executables = Array(Notifier.instances) + Array(Poller.instances) + Array(Scheduler.instances)
@@ -126,7 +130,7 @@ module GoodJob
126
130
  end
127
131
 
128
132
  # Sends +#shutdown+ or +#restart+ to executable objects ({GoodJob::Notifier}, {GoodJob::Poller}, {GoodJob::Scheduler})
129
- # @param executables [Array<(Notifier, Poller, Scheduler)>] Objects to shut down.
133
+ # @param executables [Array<Notifier, Poller, Scheduler, MultiScheduler>] Objects to shut down.
130
134
  # @param method_name [:symbol] Method to call, e.g. +:shutdown+ or +:restart+.
131
135
  # @param timeout [nil,Numeric]
132
136
  # @return [void]
@@ -6,7 +6,7 @@ module GoodJob
6
6
  # Valid execution modes.
7
7
  EXECUTION_MODES = [:async, :async_server, :external, :inline].freeze
8
8
 
9
- # @param execution_mode [nil, Symbol] specifies how and where jobs should be executed. You can also set this with the environment variable +GOOD_JOB_EXECUTION_MODE+.
9
+ # @param execution_mode [Symbol, nil] specifies how and where jobs should be executed. You can also set this with the environment variable +GOOD_JOB_EXECUTION_MODE+.
10
10
  #
11
11
  # - +:inline+ executes jobs immediately in whatever process queued them (usually the web server process). This should only be used in test and development environments.
12
12
  # - +:external+ causes the adapter to enqueue jobs, but not execute them. When using this option (the default for production environments), you'll need to use the command-line tool to actually execute your jobs.
@@ -19,9 +19,9 @@ module GoodJob
19
19
  # - +development+ and +test+: +:inline+
20
20
  # - +production+ and all other environments: +:external+
21
21
  #
22
- # @param max_threads [nil, Integer] sets the number of threads per scheduler to use when +execution_mode+ is set to +:async+. The +queues+ parameter can specify a number of threads for each group of queues which will override this value. You can also set this with the environment variable +GOOD_JOB_MAX_THREADS+. Defaults to +5+.
23
- # @param queues [nil, String] 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 +"*"+.
24
- # @param poll_interval [nil, Integer] 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+.
22
+ # @param max_threads [Integer, nil] sets the number of threads per scheduler to use when +execution_mode+ is set to +:async+. The +queues+ parameter can specify a number of threads for each group of queues which will override this value. You can also set this with the environment variable +GOOD_JOB_MAX_THREADS+. Defaults to +5+.
23
+ # @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 +"*"+.
24
+ # @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+.
25
25
  def initialize(execution_mode: nil, queues: nil, max_threads: nil, poll_interval: nil)
26
26
  if caller[0..4].find { |c| c.include?("/config/application.rb") || c.include?("/config/environments/") }
27
27
  ActiveSupport::Deprecation.warn(<<~DEPRECATION)
@@ -70,7 +70,7 @@ module GoodJob
70
70
  # Enqueues an ActiveJob job to be run at a specific time.
71
71
  # For use by Rails; you should generally not call this directly.
72
72
  # @param active_job [ActiveJob::Base] the job to be enqueued from +#perform_later+
73
- # @param timestamp [Integer] the epoch time to perform the job
73
+ # @param timestamp [Integer, nil] the epoch time to perform the job
74
74
  # @return [GoodJob::Job]
75
75
  def enqueue_at(active_job, timestamp)
76
76
  good_job = GoodJob::Job.enqueue(
@@ -97,22 +97,21 @@ module GoodJob
97
97
  end
98
98
 
99
99
  # Shut down the thread pool executors.
100
- # @param timeout [nil, Numeric] Seconds to wait for active threads.
101
- #
100
+ # @param timeout [nil, Numeric, Symbol] Seconds to wait for active threads.
102
101
  # * +nil+, the scheduler will trigger a shutdown but not wait for it to complete.
103
102
  # * +-1+, the scheduler will wait until the shutdown is complete.
104
103
  # * +0+, the scheduler will immediately shutdown and stop any threads.
105
104
  # * A positive number will wait that many seconds before stopping any remaining active threads.
106
- # @param wait [Boolean] Deprecated. Use +timeout:+ instead.
105
+ # @param wait [Boolean, nil] Deprecated. Use +timeout:+ instead.
107
106
  # @return [void]
108
107
  def shutdown(timeout: :default, wait: nil)
109
- timeout = if wait.present?
108
+ timeout = if wait.nil?
109
+ timeout
110
+ else
110
111
  ActiveSupport::Deprecation.warn(
111
112
  "Using `GoodJob::Adapter.shutdown` with `wait:` kwarg is deprecated; use `timeout:` kwarg instead e.g. GoodJob::Adapter.shutdown(timeout: #{wait ? '-1' : 'nil'})"
112
113
  )
113
114
  wait ? -1 : nil
114
- else
115
- timeout
116
115
  end
117
116
 
118
117
  timeout = if timeout == :default
@@ -126,18 +125,21 @@ module GoodJob
126
125
  end
127
126
 
128
127
  # Whether in +:async+ execution mode.
128
+ # @return [Boolean]
129
129
  def execute_async?
130
130
  @configuration.execution_mode == :async ||
131
131
  @configuration.execution_mode == :async_server && in_server_process?
132
132
  end
133
133
 
134
134
  # Whether in +:external+ execution mode.
135
+ # @return [Boolean]
135
136
  def execute_externally?
136
137
  @configuration.execution_mode == :external ||
137
138
  @configuration.execution_mode == :async_server && !in_server_process?
138
139
  end
139
140
 
140
141
  # Whether in +:inline+ execution mode.
142
+ # @return [Boolean]
141
143
  def execute_inline?
142
144
  @configuration.execution_mode == :inline
143
145
  end
@@ -145,6 +147,7 @@ module GoodJob
145
147
  private
146
148
 
147
149
  # Whether running in a web server process.
150
+ # @return [Boolean, nil]
148
151
  def in_server_process?
149
152
  return @_in_server_process if defined? @_in_server_process
150
153
 
@@ -84,9 +84,9 @@ module GoodJob
84
84
  # on the format of this string.
85
85
  # @return [String]
86
86
  def queue_string
87
- options[:queues] ||
88
- rails_config[:queues] ||
89
- env['GOOD_JOB_QUEUES'] ||
87
+ options[:queues].presence ||
88
+ rails_config[:queues].presence ||
89
+ env['GOOD_JOB_QUEUES'].presence ||
90
90
  '*'
91
91
  end
92
92
 
@@ -3,7 +3,6 @@ require 'active_support/core_ext/module/attribute_accessors_per_thread'
3
3
  module GoodJob
4
4
  # Thread-local attributes for passing values from Instrumentation.
5
5
  # (Cannot use ActiveSupport::CurrentAttributes because ActiveJob resets it)
6
-
7
6
  module CurrentExecution
8
7
  # @!attribute [rw] error_on_retry
9
8
  # @!scope class
@@ -13,6 +13,7 @@ module GoodJob
13
13
  end
14
14
 
15
15
  # Daemonizes the current process and writes out a pidfile.
16
+ # @return [void]
16
17
  def daemonize
17
18
  check_pid
18
19
  Process.daemon
@@ -21,6 +22,7 @@ module GoodJob
21
22
 
22
23
  private
23
24
 
25
+ # @return [void]
24
26
  def write_pid
25
27
  File.open(pidfile, ::File::CREAT | ::File::EXCL | ::File::WRONLY) { |f| f.write(Process.pid.to_s) }
26
28
  at_exit { File.delete(pidfile) if File.exist?(pidfile) }
@@ -29,10 +31,12 @@ module GoodJob
29
31
  retry
30
32
  end
31
33
 
34
+ # @return [void]
32
35
  def delete_pid
33
36
  File.delete(pidfile) if File.exist?(pidfile)
34
37
  end
35
38
 
39
+ # @return [void]
36
40
  def check_pid
37
41
  case pid_status(pidfile)
38
42
  when :running, :not_owned
@@ -42,6 +46,8 @@ module GoodJob
42
46
  end
43
47
  end
44
48
 
49
+ # @param pidfile [Pathname, String]
50
+ # @return [Symbol]
45
51
  def pid_status(pidfile)
46
52
  return :exited unless File.exist?(pidfile)
47
53
 
data/lib/good_job/job.rb CHANGED
@@ -50,6 +50,14 @@ module GoodJob
50
50
  end
51
51
  end
52
52
 
53
+ # Get Jobs with given class name
54
+ # @!method with_job_class
55
+ # @!scope class
56
+ # @param string [String]
57
+ # Job class name
58
+ # @return [ActiveRecord::Relation]
59
+ scope :with_job_class, ->(job_class) { where("serialized_params->>'job_class' = ?", job_class) }
60
+
53
61
  # Get Jobs that have not yet been completed.
54
62
  # @!method unfinished
55
63
  # @!scope class
@@ -94,6 +102,12 @@ module GoodJob
94
102
  # @return [ActiveRecord::Relation]
95
103
  scope :finished, ->(timestamp = nil) { timestamp ? where(arel_table['finished_at'].lteq(timestamp)) : where.not(finished_at: nil) }
96
104
 
105
+ # Get Jobs that started but not finished yet.
106
+ # @!method running
107
+ # @!scope class
108
+ # @return [ActiveRecord::Relation]
109
+ scope :running, -> { where.not(performed_at: nil).where(finished_at: nil) }
110
+
97
111
  # Get Jobs on queues that match the given queue string.
98
112
  # @!method queue_string(string)
99
113
  # @!scope class
@@ -235,7 +249,7 @@ module GoodJob
235
249
 
236
250
  private
237
251
 
238
- # @return [GoodJob::ExecutionResult]
252
+ # @return [ExecutionResult]
239
253
  def execute
240
254
  params = serialized_params.merge(
241
255
  "provider_job_id" => id
@@ -24,7 +24,7 @@ module GoodJob
24
24
  end
25
25
 
26
26
  # Perform the next eligible job
27
- # @return [nil, Object] Returns job result or +nil+ if no job was found
27
+ # @return [Object, nil] Returns job result or +nil+ if no job was found
28
28
  def next
29
29
  job_query.perform_with_advisory_lock
30
30
  end
@@ -54,7 +54,7 @@ module GoodJob
54
54
  # @param after [DateTime, Time, nil] future jobs scheduled after this time
55
55
  # @param limit [Integer] number of future timestamps to return
56
56
  # @param now_limit [Integer] number of past timestamps to return
57
- # @return [Array<(Time, DateTime)>, nil]
57
+ # @return [Array<DateTime, Time>, nil]
58
58
  def next_at(after: nil, limit: nil, now_limit: nil)
59
59
  job_query.next_scheduled_at(after: after, limit: limit, now_limit: now_limit)
60
60
  end
@@ -245,11 +245,8 @@ module GoodJob
245
245
 
246
246
  private
247
247
 
248
- def sanitize_sql_for_conditions(*args)
249
- # Made public in Rails 5.2
250
- self.class.send(:sanitize_sql_for_conditions, *args)
251
- end
252
-
248
+ # @param query [String]
249
+ # @return [Boolean]
253
250
  def pg_or_jdbc_query(query)
254
251
  if Concurrent.on_jruby?
255
252
  # Replace $1 bind parameters with ?
@@ -14,6 +14,7 @@ module GoodJob
14
14
 
15
15
  # @!macro notification_responder
16
16
  # Responds to the +$0.good_job+ notification.
17
+ # @param event [ActiveSupport::Notifications::Event]
17
18
  # @return [void]
18
19
  def create(event)
19
20
  # FIXME: This method does not match any good_job notifications.
@@ -24,7 +25,7 @@ module GoodJob
24
25
  end
25
26
  end
26
27
 
27
- # @macro notification_responder
28
+ # @!macro notification_responder
28
29
  def finished_timer_task(event)
29
30
  exception = event.payload[:error]
30
31
  return unless exception
@@ -34,7 +35,7 @@ module GoodJob
34
35
  end
35
36
  end
36
37
 
37
- # @macro notification_responder
38
+ # @!macro notification_responder
38
39
  def finished_job_task(event)
39
40
  exception = event.payload[:error]
40
41
  return unless exception
@@ -44,7 +45,7 @@ module GoodJob
44
45
  end
45
46
  end
46
47
 
47
- # @macro notification_responder
48
+ # @!macro notification_responder
48
49
  def scheduler_create_pool(event)
49
50
  max_threads = event.payload[:max_threads]
50
51
  performer_name = event.payload[:performer_name]
@@ -55,7 +56,7 @@ module GoodJob
55
56
  end
56
57
  end
57
58
 
58
- # @macro notification_responder
59
+ # @!macro notification_responder
59
60
  def scheduler_shutdown_start(event)
60
61
  process_id = event.payload[:process_id]
61
62
 
@@ -64,7 +65,7 @@ module GoodJob
64
65
  end
65
66
  end
66
67
 
67
- # @macro notification_responder
68
+ # @!macro notification_responder
68
69
  def scheduler_shutdown(event)
69
70
  process_id = event.payload[:process_id]
70
71
 
@@ -73,7 +74,7 @@ module GoodJob
73
74
  end
74
75
  end
75
76
 
76
- # @macro notification_responder
77
+ # @!macro notification_responder
77
78
  def scheduler_restart_pools(event)
78
79
  process_id = event.payload[:process_id]
79
80
 
@@ -82,7 +83,7 @@ module GoodJob
82
83
  end
83
84
  end
84
85
 
85
- # @macro notification_responder
86
+ # @!macro notification_responder
86
87
  def perform_job(event)
87
88
  good_job = event.payload[:good_job]
88
89
  process_id = event.payload[:process_id]
@@ -93,14 +94,14 @@ module GoodJob
93
94
  end
94
95
  end
95
96
 
96
- # @macro notification_responder
97
- def notifier_listen(_event)
97
+ # @!macro notification_responder
98
+ def notifier_listen(event) # rubocop:disable Lint/UnusedMethodArgument
98
99
  info do
99
100
  "Notifier subscribed with LISTEN"
100
101
  end
101
102
  end
102
103
 
103
- # @macro notification_responder
104
+ # @!macro notification_responder
104
105
  def notifier_notified(event)
105
106
  payload = event.payload[:payload]
106
107
 
@@ -109,7 +110,7 @@ module GoodJob
109
110
  end
110
111
  end
111
112
 
112
- # @macro notification_responder
113
+ # @!macro notification_responder
113
114
  def notifier_notify_error(event)
114
115
  error = event.payload[:error]
115
116
 
@@ -118,14 +119,14 @@ module GoodJob
118
119
  end
119
120
  end
120
121
 
121
- # @macro notification_responder
122
- def notifier_unlisten(_event)
122
+ # @!macro notification_responder
123
+ def notifier_unlisten(event) # rubocop:disable Lint/UnusedMethodArgument
123
124
  info do
124
125
  "Notifier unsubscribed with UNLISTEN"
125
126
  end
126
127
  end
127
128
 
128
- # @macro notification_responder
129
+ # @!macro notification_responder
129
130
  def cleanup_preserved_jobs(event)
130
131
  timestamp = event.payload[:timestamp]
131
132
  deleted_records_count = event.payload[:deleted_records_count]
@@ -4,31 +4,40 @@ module GoodJob
4
4
  # @return [Array<Scheduler>] List of the scheduler delegates
5
5
  attr_reader :schedulers
6
6
 
7
+ # @param schedulers [Array<Scheduler>]
7
8
  def initialize(schedulers)
8
9
  @schedulers = schedulers
9
10
  end
10
11
 
11
12
  # Delegates to {Scheduler#running?}.
13
+ # @return [Boolean, nil]
12
14
  def running?
13
15
  schedulers.all?(&:running?)
14
16
  end
15
17
 
16
18
  # Delegates to {Scheduler#shutdown?}.
19
+ # @return [Boolean, nil]
17
20
  def shutdown?
18
21
  schedulers.all?(&:shutdown?)
19
22
  end
20
23
 
21
24
  # Delegates to {Scheduler#shutdown}.
25
+ # @param timeout [Numeric, nil]
26
+ # @return [void]
22
27
  def shutdown(timeout: -1)
23
28
  GoodJob._shutdown_all(schedulers, timeout: timeout)
24
29
  end
25
30
 
26
31
  # Delegates to {Scheduler#restart}.
32
+ # @param timeout [Numeric, nil]
33
+ # @return [void]
27
34
  def restart(timeout: -1)
28
35
  GoodJob._shutdown_all(schedulers, :restart, timeout: timeout)
29
36
  end
30
37
 
31
38
  # Delegates to {Scheduler#create_thread}.
39
+ # @param state [Hash]
40
+ # @return [Boolean, nil]
32
41
  def create_thread(state = nil)
33
42
  results = []
34
43
 
@@ -30,7 +30,7 @@ module GoodJob # :nodoc:
30
30
  # @!attribute [r] instances
31
31
  # @!scope class
32
32
  # List of all instantiated Notifiers in the current process.
33
- # @return [Array<GoodJob::Adapter>]
33
+ # @return [Array<GoodJob::Notifier>, nil]
34
34
  cattr_reader :instances, default: [], instance_reader: false
35
35
 
36
36
  # Send a message via Postgres NOTIFY
@@ -64,17 +64,19 @@ module GoodJob # :nodoc:
64
64
  end
65
65
 
66
66
  # Tests whether the notifier is running.
67
+ # @!method running?
67
68
  # @return [true, false, nil]
68
69
  delegate :running?, to: :executor, allow_nil: true
69
70
 
70
71
  # Tests whether the scheduler is shutdown.
72
+ # @!method shutdown?
71
73
  # @return [true, false, nil]
72
74
  delegate :shutdown?, to: :executor, allow_nil: true
73
75
 
74
76
  # Shut down the notifier.
75
77
  # This stops the background LISTENing thread.
76
78
  # Use {#shutdown?} to determine whether threads have stopped.
77
- # @param timeout [nil, Numeric] Seconds to wait for active threads.
79
+ # @param timeout [Numeric, nil] Seconds to wait for active threads.
78
80
  # * +nil+, the scheduler will trigger a shutdown but not wait for it to complete.
79
81
  # * +-1+, the scheduler will wait until the shutdown is complete.
80
82
  # * +0+, the scheduler will immediately shutdown and stop any threads.
@@ -16,7 +16,7 @@ module GoodJob # :nodoc:
16
16
  # @!attribute [r] instances
17
17
  # @!scope class
18
18
  # List of all instantiated Pollers in the current process.
19
- # @return [Array<GoodJob::Poller>]
19
+ # @return [Array<GoodJob::Poller>, nil]
20
20
  cattr_reader :instances, default: [], instance_reader: false
21
21
 
22
22
  # Creates GoodJob::Poller from a GoodJob::Configuration instance.
@@ -30,8 +30,8 @@ module GoodJob # :nodoc:
30
30
  # @return [Array<#call, Array(Object, Symbol)>]
31
31
  attr_reader :recipients
32
32
 
33
- # @param recipients [Array<#call, Array(Object, Symbol)>]
34
- # @param poll_interval [Hash] number of seconds between polls
33
+ # @param recipients [Array<Proc, #call, Array(Object, Symbol)>]
34
+ # @param poll_interval [Integer, nil] number of seconds between polls
35
35
  def initialize(*recipients, poll_interval: nil)
36
36
  @recipients = Concurrent::Array.new(recipients)
37
37
 
@@ -72,7 +72,7 @@ module GoodJob # :nodoc:
72
72
 
73
73
  # Restart the poller.
74
74
  # When shutdown, start; or shutdown and start.
75
- # @param timeout [nil, Numeric] Seconds to wait; shares same values as {#shutdown}.
75
+ # @param timeout [Numeric, nil] Seconds to wait; shares same values as {#shutdown}.
76
76
  # @return [void]
77
77
  def restart(timeout: -1)
78
78
  shutdown(timeout: timeout) if running?
@@ -81,6 +81,9 @@ module GoodJob # :nodoc:
81
81
 
82
82
  # Invoked on completion of TimerTask task.
83
83
  # @!visibility private
84
+ # @param time [Integer]
85
+ # @param executed_task [Object, nil]
86
+ # @param thread_error [Exception, nil]
84
87
  # @return [void]
85
88
  def timer_observer(time, executed_task, thread_error)
86
89
  GoodJob.on_thread_error.call(thread_error) if thread_error && GoodJob.on_thread_error.respond_to?(:call)
@@ -89,8 +92,10 @@ module GoodJob # :nodoc:
89
92
 
90
93
  private
91
94
 
95
+ # @return [Concurrent::TimerTask]
92
96
  attr_reader :timer
93
97
 
98
+ # @return [void]
94
99
  def create_timer
95
100
  return if @timer_options[:execution_interval] <= 0
96
101
 
@@ -30,7 +30,7 @@ module GoodJob # :nodoc:
30
30
  # @!attribute [r] instances
31
31
  # @!scope class
32
32
  # List of all instantiated Schedulers in the current process.
33
- # @return [Array<GoodJob::Scheduler>]
33
+ # @return [Array<GoodJob::Scheduler>, nil]
34
34
  cattr_reader :instances, default: [], instance_reader: false
35
35
 
36
36
  # Creates GoodJob::Scheduler(s) and Performers from a GoodJob::Configuration instance.
@@ -82,17 +82,17 @@ module GoodJob # :nodoc:
82
82
  end
83
83
 
84
84
  # Tests whether the scheduler is running.
85
- # @return [true, false, nil]
85
+ # @return [Boolean, nil]
86
86
  delegate :running?, to: :executor, allow_nil: true
87
87
 
88
88
  # Tests whether the scheduler is shutdown.
89
- # @return [true, false, nil]
89
+ # @return [Boolean, nil]
90
90
  delegate :shutdown?, to: :executor, allow_nil: true
91
91
 
92
92
  # Shut down the scheduler.
93
93
  # This stops all threads in the thread pool.
94
94
  # Use {#shutdown?} to determine whether threads have stopped.
95
- # @param timeout [nil, Numeric] Seconds to wait for actively executing jobs to finish
95
+ # @param timeout [Numeric, nil] Seconds to wait for actively executing jobs to finish
96
96
  # * +nil+, the scheduler will trigger a shutdown but not wait for it to complete.
97
97
  # * +-1+, the scheduler will wait until the shutdown is complete.
98
98
  # * +0+, the scheduler will immediately shutdown and stop any active tasks.
@@ -128,8 +128,8 @@ module GoodJob # :nodoc:
128
128
  end
129
129
 
130
130
  # Wakes a thread to allow the performer to execute a task.
131
- # @param state [nil, Object] Contextual information for the performer. See {JobPerformer#next?}.
132
- # @return [nil, Boolean] Whether work was started.
131
+ # @param state [Hash, nil] Contextual information for the performer. See {JobPerformer#next?}.
132
+ # @return [Boolean, nil] Whether work was started.
133
133
  #
134
134
  # * +nil+ if the scheduler is unable to take new work, for example if the thread pool is shut down or at capacity.
135
135
  # * +true+ if the performer started executing work.
@@ -215,6 +215,7 @@ module GoodJob # :nodoc:
215
215
 
216
216
  attr_reader :performer, :executor, :timer_set
217
217
 
218
+ # @return [void]
218
219
  def create_executor
219
220
  instrument("scheduler_create_pool", { performer_name: performer.name, max_threads: @executor_options[:max_threads] }) do
220
221
  @timer_set = TimerSet.new
@@ -222,6 +223,8 @@ module GoodJob # :nodoc:
222
223
  end
223
224
  end
224
225
 
226
+ # @param delay [Integer]
227
+ # @return [void]
225
228
  def create_task(delay = 0)
226
229
  future = Concurrent::ScheduledTask.new(delay, args: [performer], executor: executor, timer_set: timer_set) do |thr_performer|
227
230
  Rails.application.executor.wrap do
@@ -232,6 +235,9 @@ module GoodJob # :nodoc:
232
235
  future.execute
233
236
  end
234
237
 
238
+ # @param name [String]
239
+ # @param payload [Hash]
240
+ # @return [void]
235
241
  def instrument(name, payload = {}, &block)
236
242
  payload = payload.reverse_merge({
237
243
  scheduler: self,
@@ -1,4 +1,4 @@
1
1
  module GoodJob
2
2
  # GoodJob gem version.
3
- VERSION = '1.9.3'.freeze
3
+ VERSION = '1.9.4'.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.9.3
4
+ version: 1.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Sheldon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-05-10 00:00:00.000000000 Z
11
+ date: 2021-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob