Class: GoodJob::Configuration
- Inherits:
-
Object
- Object
- GoodJob::Configuration
- Defined in:
- lib/good_job/configuration.rb
Overview
GoodJob::Configuration provides normalized configuration information to the rest of GoodJob. It combines environment information with explicitly set options to get the final values for each option.
Constant Summary collapse
- EXECUTION_MODES =
Valid execution modes.
[:async, :async_all, :async_server, :external, :inline].freeze
- DEFAULT_MAX_THREADS =
Default number of threads to use per Scheduler
5- DEFAULT_POLL_INTERVAL =
Default number of seconds between polls for jobs
10- DEFAULT_DEVELOPMENT_ASYNC_POLL_INTERVAL =
Default poll interval for async in development environment
-1 # Default number of threads to use per {Scheduler}
- DEFAULT_MAX_CACHE =
Default number of threads to use per Scheduler
10_000- DEFAULT_CLEANUP_PRESERVED_JOBS_BEFORE_SECONDS_AGO =
Default number of seconds to preserve jobs for GoodJob::CLI#cleanup_preserved_jobs and GoodJob.cleanup_preserved_jobs
14.days.to_i
- DEFAULT_CLEANUP_INTERVAL_JOBS =
Default number of jobs to execute between preserved job cleanup runs
1_000- DEFAULT_CLEANUP_INTERVAL_SECONDS =
Default number of seconds to wait between preserved job cleanup runs
10.minutes.to_i
- DEFAULT_SHUTDOWN_TIMEOUT =
Default to always wait for jobs to finish for Adapter#shutdown
-1 # Default to not running cron
- DEFAULT_ENABLE_CRON =
Default to not running cron
false- DEFAULT_ENABLE_LISTEN_NOTIFY =
Default to enabling LISTEN/NOTIFY
true- DEFAULT_DASHBOARD_DEFAULT_LOCALE =
Default Dashboard I18n locale
:en- DEFAULT_DASHBOARD_LIVE_POLL_ENABLED =
Default Dashboard Live Poll button enabled
true- DEFAULT_ENQUEUE_AFTER_TRANSACTION_COMMIT =
Default enqueue_after_transaction_commit
false- DEFAULT_ENABLE_PAUSES =
Default enable_pauses setting
false- DEFAULT_QUEUE_SELECT_LIMIT =
Default number of candidate jobs to query when polling
1_000- DEQUEUE_QUERY_SORTS =
Valid dequeue query sorts
[:created_at, :scheduled_at].freeze
- LOCK_STRATEGIES =
Valid lock strategies
[:advisory, :skiplocked, :hybrid].freeze
Instance Attribute Summary collapse
-
#env ⇒ Hash
readonly
The environment from which to read GoodJob’s environment variables.
-
#options ⇒ Hash
readonly
The options that were explicitly set when initializing
Configuration.
Class Method Summary collapse
-
.total_estimated_threads(warn: false) ⇒ Integer
Returns the maximum number of threads GoodJob might consume.
- .validate_dequeue_query_sort(dequeue_query_sort) ⇒ Object
- .validate_execution_mode(execution_mode) ⇒ Object
Instance Method Summary collapse
-
#advisory_lock_heartbeat ⇒ Boolean
Whether to take an advisory lock on the process record in the notifier reactor.
-
#cleanup_discarded_jobs? ⇒ Boolean
Whether to automatically destroy discarded jobs that have been preserved.
-
#cleanup_interval_jobs ⇒ Integer, ...
Number of jobs a Scheduler will execute before automatically cleaning up preserved jobs.
-
#cleanup_interval_seconds ⇒ Integer, ...
Number of seconds a Scheduler will wait before automatically cleaning up preserved jobs.
-
#cleanup_preserved_jobs_before_seconds_ago ⇒ Integer
Number of seconds to preserve jobs before automatic destruction.
- #cron ⇒ Object
- #cron_entries ⇒ Object
- #cron_graceful_restart_period ⇒ Object
-
#daemonize? ⇒ Boolean
Tests whether to daemonize the process.
- #dashboard_default_locale ⇒ Object
- #dashboard_live_poll_enabled ⇒ Object
- #dequeue_query_sort ⇒ Object
-
#enable_cron ⇒ Boolean
(also: #enable_cron?)
Whether to run cron.
- #enable_listen_notify ⇒ Object
-
#enable_pauses ⇒ Boolean
Whether the job processing can be paused.
-
#enqueue_after_transaction_commit ⇒ Boolean
Whether the Adapter should have Active Job enqueue jobs after the transaction has committed.
-
#execution_mode ⇒ Symbol
Specifies how and where jobs should be executed.
-
#idle_timeout ⇒ Integer?
The number of seconds that a good_job process will idle with out running a job before exiting.
-
#in_webserver? ⇒ Boolean?
Whether running in a web server process.
-
#initialize(options, env: ENV) ⇒ Configuration
constructor
A new instance of Configuration.
- #inline_execution_respects_schedule? ⇒ Boolean
-
#lock_strategy ⇒ Symbol
Strategy for locking jobs during dequeue.
- #lower_thread_priority ⇒ Object
-
#max_cache ⇒ Integer
The maximum number of future-scheduled jobs to store in memory.
-
#max_threads ⇒ Integer
Indicates the number of threads to use per Scheduler.
-
#pidfile ⇒ Pathname, String
Path of the pidfile to create when running as a daemon.
-
#poll_interval ⇒ Integer
The number of seconds between polls for jobs.
-
#probe_app ⇒ nil, Class
Rack compliant application to be run on the ProbeServer.
-
#probe_handler ⇒ nil, Symbol
Probe server handler.
-
#probe_port ⇒ nil, Integer
Port of the probe server.
-
#queue_select_limit ⇒ Integer
The number of queued jobs to select when polling for a job to run.
-
#queue_string ⇒ String
Describes which queues to execute jobs from and how those queues should be grouped into Scheduler instances.
-
#shutdown_timeout ⇒ Float
The number of seconds to wait for jobs to finish when shutting down before stopping the thread.
- #validate! ⇒ Object
Constructor Details
#initialize(options, env: ENV) ⇒ Configuration
Returns a new instance of Configuration.
97 98 99 100 101 102 |
# File 'lib/good_job/configuration.rb', line 97 def initialize(, env: ENV) @options = @env = env @_in_webserver = nil end |
Instance Attribute Details
#env ⇒ Hash (readonly)
The environment from which to read GoodJob’s environment variables. By default, this is the current process’s environment, but it can be set to something else in #initialize.
66 67 68 |
# File 'lib/good_job/configuration.rb', line 66 def env @env end |
#options ⇒ Hash (readonly)
The options that were explicitly set when initializing Configuration. It is safe to modify this hash in place; be sure to symbolize keys.
60 61 62 |
# File 'lib/good_job/configuration.rb', line 60 def @options end |
Class Method Details
.total_estimated_threads(warn: false) ⇒ Integer
Returns the maximum number of threads GoodJob might consume
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/good_job/configuration.rb', line 71 def self.total_estimated_threads(warn: false) utility_threads = GoodJob::SharedExecutor::MAX_THREADS scheduler_threads = GoodJob::Scheduler.instances.sum { |scheduler| scheduler.stats[:max_threads] } good_job_threads = utility_threads + scheduler_threads puma_threads = (Puma::Server.current&.max_threads if defined?(Puma::Server)) || 0 total_threads = good_job_threads + puma_threads activerecord_pool_size = ActiveRecord::Base.connection_pool&.size if warn && activerecord_pool_size && total_threads > activerecord_pool_size = "GoodJob is using #{good_job_threads} threads, " \ "#{" and Puma is using #{puma_threads} threads, " if puma_threads.positive?}" \ "which is #{total_threads - activerecord_pool_size} thread(s) more than ActiveRecord's database connection pool size of #{activerecord_pool_size}. " \ "Consider increasing ActiveRecord's database connection pool size in config/database.yml." GoodJob.logger.warn end good_job_threads end |
.validate_dequeue_query_sort(dequeue_query_sort) ⇒ Object
53 54 55 |
# File 'lib/good_job/configuration.rb', line 53 def self.validate_dequeue_query_sort(dequeue_query_sort) raise ArgumentError, "GoodJob dequeue query sortmust be one of #{DEQUEUE_QUERY_SORTS.join(', ')}. It was '#{dequeue_query_sort}' which is not valid." unless dequeue_query_sort.in?(DEQUEUE_QUERY_SORTS) end |
.validate_execution_mode(execution_mode) ⇒ Object
49 50 51 |
# File 'lib/good_job/configuration.rb', line 49 def self.validate_execution_mode(execution_mode) raise ArgumentError, "GoodJob execution mode must be one of #{EXECUTION_MODES.join(', ')}. It was '#{execution_mode}' which is not valid." unless execution_mode.in?(EXECUTION_MODES) end |
Instance Method Details
#advisory_lock_heartbeat ⇒ Boolean
Whether to take an advisory lock on the process record in the notifier reactor.
434 435 436 437 438 439 440 |
# File 'lib/good_job/configuration.rb', line 434 def advisory_lock_heartbeat return [:advisory_lock_heartbeat] unless [:advisory_lock_heartbeat].nil? return rails_config[:advisory_lock_heartbeat] unless rails_config[:advisory_lock_heartbeat].nil? return ActiveModel::Type::Boolean.new.cast(env['GOOD_JOB_ADVISORY_LOCK_HEARTBEAT']) unless env['GOOD_JOB_ADVISORY_LOCK_HEARTBEAT'].nil? Rails.env.development? end |
#cleanup_discarded_jobs? ⇒ Boolean
Whether to automatically destroy discarded jobs that have been preserved.
269 270 271 272 273 274 |
# File 'lib/good_job/configuration.rb', line 269 def cleanup_discarded_jobs? return rails_config[:cleanup_discarded_jobs] unless rails_config[:cleanup_discarded_jobs].nil? return ActiveModel::Type::Boolean.new.cast(env['GOOD_JOB_CLEANUP_DISCARDED_JOBS']) unless env['GOOD_JOB_CLEANUP_DISCARDED_JOBS'].nil? true end |
#cleanup_interval_jobs ⇒ Integer, ...
Number of jobs a Scheduler will execute before automatically cleaning up preserved jobs. Positive values will clean up after that many jobs have run, false or 0 will disable, and -1 will clean up after every job.
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/good_job/configuration.rb', line 290 def cleanup_interval_jobs value = if rails_config.key?(:cleanup_interval_jobs) rails_config[:cleanup_interval_jobs] elsif env.key?('GOOD_JOB_CLEANUP_INTERVAL_JOBS') env['GOOD_JOB_CLEANUP_INTERVAL_JOBS'] end if value.in? [nil, "", true] DEFAULT_CLEANUP_INTERVAL_JOBS elsif value.in? [0, "0", false, "false"] false else value ? value.to_i : false end end |
#cleanup_interval_seconds ⇒ Integer, ...
Number of seconds a Scheduler will wait before automatically cleaning up preserved jobs. Positive values will clean up after that many jobs have run, false or 0 will disable, and -1 will clean up after every job.
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/good_job/configuration.rb', line 309 def cleanup_interval_seconds value = if rails_config.key?(:cleanup_interval_seconds) rails_config[:cleanup_interval_seconds] elsif env.key?('GOOD_JOB_CLEANUP_INTERVAL_SECONDS') env['GOOD_JOB_CLEANUP_INTERVAL_SECONDS'] end if value.nil? || value == "" || value == true DEFAULT_CLEANUP_INTERVAL_SECONDS elsif value.in? [0, "0", false, "false"] false else value ? value.to_i : false end end |
#cleanup_preserved_jobs_before_seconds_ago ⇒ Integer
Number of seconds to preserve jobs before automatic destruction.
278 279 280 281 282 283 284 285 |
# File 'lib/good_job/configuration.rb', line 278 def cleanup_preserved_jobs_before_seconds_ago ( [:before_seconds_ago] || rails_config[:cleanup_preserved_jobs_before_seconds_ago] || env['GOOD_JOB_CLEANUP_PRESERVED_JOBS_BEFORE_SECONDS_AGO'] || DEFAULT_CLEANUP_PRESERVED_JOBS_BEFORE_SECONDS_AGO ).to_i end |
#cron ⇒ Object
223 224 225 226 227 228 229 230 231 |
# File 'lib/good_job/configuration.rb', line 223 def cron env_cron = JSON.parse(ENV.fetch('GOOD_JOB_CRON'), symbolize_names: true) if ENV['GOOD_JOB_CRON'].present? rails_config_cron = rails_config[:cron].presence [:cron] || rails_config_cron || env_cron || {} end |
#cron_entries ⇒ Object
233 234 235 |
# File 'lib/good_job/configuration.rb', line 233 def cron_entries cron.map { |cron_key, params| GoodJob::CronEntry.new(params.merge(key: cron_key)) } end |
#cron_graceful_restart_period ⇒ Object
237 238 239 240 241 |
# File 'lib/good_job/configuration.rb', line 237 def cron_graceful_restart_period [:cron_graceful_restart_period] || rails_config[:cron_graceful_restart_period] || env['GOOD_JOB_CRON_GRACEFUL_RESTART_PERIOD'] end |
#daemonize? ⇒ Boolean
Tests whether to daemonize the process.
327 328 329 |
# File 'lib/good_job/configuration.rb', line 327 def daemonize? [:daemonize] || false end |
#dashboard_default_locale ⇒ Object
370 371 372 |
# File 'lib/good_job/configuration.rb', line 370 def dashboard_default_locale rails_config[:dashboard_default_locale] || DEFAULT_DASHBOARD_DEFAULT_LOCALE end |
#dashboard_live_poll_enabled ⇒ Object
374 375 376 377 378 |
# File 'lib/good_job/configuration.rb', line 374 def dashboard_live_poll_enabled return rails_config[:dashboard_live_poll_enabled] unless rails_config[:dashboard_live_poll_enabled].nil? DEFAULT_DASHBOARD_LIVE_POLL_ENABLED end |
#dequeue_query_sort ⇒ Object
442 443 444 |
# File 'lib/good_job/configuration.rb', line 442 def dequeue_query_sort ([:dequeue_query_sort] || rails_config[:dequeue_query_sort] || :created_at).to_sym end |
#enable_cron ⇒ Boolean Also known as: enable_cron?
Whether to run cron
211 212 213 214 215 216 217 218 219 |
# File 'lib/good_job/configuration.rb', line 211 def enable_cron value = ActiveModel::Type::Boolean.new.cast( [:enable_cron] || rails_config[:enable_cron] || env['GOOD_JOB_ENABLE_CRON'] || false ) value && cron.size.positive? end |
#enable_listen_notify ⇒ Object
362 363 364 365 366 367 368 |
# File 'lib/good_job/configuration.rb', line 362 def enable_listen_notify return [:enable_listen_notify] unless [:enable_listen_notify].nil? return rails_config[:enable_listen_notify] unless rails_config[:enable_listen_notify].nil? return ActiveModel::Type::Boolean.new.cast(env['GOOD_JOB_ENABLE_LISTEN_NOTIFY']) unless env['GOOD_JOB_ENABLE_LISTEN_NOTIFY'].nil? DEFAULT_ENABLE_LISTEN_NOTIFY end |
#enable_pauses ⇒ Boolean
Whether the job processing can be paused.
391 392 393 394 395 396 397 |
# File 'lib/good_job/configuration.rb', line 391 def enable_pauses return [:enable_pauses] unless [:enable_pauses].nil? return rails_config[:enable_pauses] unless rails_config[:enable_pauses].nil? return ActiveModel::Type::Boolean.new.cast(env['GOOD_JOB_ENABLE_PAUSES']) unless env['GOOD_JOB_ENABLE_PAUSES'].nil? DEFAULT_ENABLE_PAUSES end |
#enqueue_after_transaction_commit ⇒ Boolean
Whether the Adapter should have Active Job enqueue jobs after the transaction has committed.
382 383 384 385 386 387 |
# File 'lib/good_job/configuration.rb', line 382 def enqueue_after_transaction_commit return [:enqueue_after_transaction_commit] unless [:enqueue_after_transaction_commit].nil? return rails_config[:enqueue_after_transaction_commit] unless rails_config[:enqueue_after_transaction_commit].nil? DEFAULT_ENQUEUE_AFTER_TRANSACTION_COMMIT end |
#execution_mode ⇒ Symbol
Specifies how and where jobs should be executed. See Adapter#initialize for more details on possible values.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/good_job/configuration.rb', line 112 def execution_mode mode = [:execution_mode] || rails_config[:execution_mode] || env['GOOD_JOB_EXECUTION_MODE'] mode = mode.to_sym if mode if mode if GoodJob::CLI.within_exe? && [:async, :async_server].include?(mode) :external else mode end elsif GoodJob::CLI.within_exe? :external elsif Rails.env.development? :async elsif Rails.env.test? :inline else # rubocop:disable Lint/DuplicateBranch :external end end |
#idle_timeout ⇒ Integer?
The number of seconds that a good_job process will idle with out running a job before exiting
259 260 261 262 263 264 265 |
# File 'lib/good_job/configuration.rb', line 259 def idle_timeout ( [:idle_timeout] || rails_config[:idle_timeout] || env['GOOD_JOB_IDLE_TIMEOUT'] )&.to_i || nil end |
#in_webserver? ⇒ Boolean?
Whether running in a web server process.
412 413 414 415 416 417 418 419 420 421 422 |
# File 'lib/good_job/configuration.rb', line 412 def in_webserver? return @_in_webserver unless @_in_webserver.nil? @_in_webserver = Rails.const_defined?(:Server) || begin self_caller = caller self_caller.grep(%r{config.ru}).any? || # EXAMPLE: config.ru:3:in `block in <main>' OR config.ru:3:in `new_from_string' self_caller.grep(%r{puma/request}).any? || # EXAMPLE: puma-5.6.4/lib/puma/request.rb:76:in `handle_request' self_caller.grep(%{/rack/handler/}).any? || # EXAMPLE: iodine-0.7.44/lib/rack/handler/iodine.rb:13:in `start' (Concurrent.on_jruby? && self_caller.grep(%r{jruby/rack/rails_booter}).any?) # EXAMPLE: uri:classloader:/jruby/rack/rails_booter.rb:83:in `load_environment' end || false end |
#inline_execution_respects_schedule? ⇒ Boolean
180 181 182 |
# File 'lib/good_job/configuration.rb', line 180 def inline_execution_respects_schedule? !!rails_config[:inline_execution_respects_schedule] end |
#lock_strategy ⇒ Symbol
Strategy for locking jobs during dequeue.
401 402 403 404 405 406 407 408 |
# File 'lib/good_job/configuration.rb', line 401 def lock_strategy ( [:lock_strategy] || rails_config[:lock_strategy] || env['GOOD_JOB_LOCK_STRATEGY'] || :advisory )&.to_sym end |
#lower_thread_priority ⇒ Object
424 425 426 427 428 429 430 |
# File 'lib/good_job/configuration.rb', line 424 def lower_thread_priority return [:lower_thread_priority] unless [:lower_thread_priority].nil? return rails_config[:lower_thread_priority] unless rails_config[:lower_thread_priority].nil? return ActiveModel::Type::Boolean.new.cast(env['GOOD_JOB_LOWER_THREAD_PRIORITY']) unless env['GOOD_JOB_LOWER_THREAD_PRIORITY'].nil? nil end |
#max_cache ⇒ Integer
The maximum number of future-scheduled jobs to store in memory. Storing future-scheduled jobs in memory reduces execution latency at the cost of increased memory usage. 10,000 stored jobs = ~20MB.
188 189 190 191 192 193 194 195 |
# File 'lib/good_job/configuration.rb', line 188 def max_cache ( [:max_cache] || rails_config[:max_cache] || env['GOOD_JOB_MAX_CACHE'] || DEFAULT_MAX_CACHE ).to_i end |
#max_threads ⇒ Integer
Indicates the number of threads to use per Scheduler. Note that #queue_string may provide more specific thread counts to use with individual schedulers.
139 140 141 142 143 144 145 146 147 |
# File 'lib/good_job/configuration.rb', line 139 def max_threads ( [:max_threads] || rails_config[:max_threads] || env['GOOD_JOB_MAX_THREADS'] || env['RAILS_MAX_THREADS'] || DEFAULT_MAX_THREADS ).to_i end |
#pidfile ⇒ Pathname, String
Path of the pidfile to create when running as a daemon.
333 334 335 336 337 |
# File 'lib/good_job/configuration.rb', line 333 def pidfile [:pidfile] || env['GOOD_JOB_PIDFILE'] || Rails.application.root.join('tmp', 'pids', 'good_job.pid') end |
#poll_interval ⇒ Integer
The number of seconds between polls for jobs. GoodJob will execute jobs on queues continuously until a queue is empty, at which point it will poll (using this interval) for new queued jobs to execute.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/good_job/configuration.rb', line 165 def poll_interval interval = [:poll_interval] || rails_config[:poll_interval] || env['GOOD_JOB_POLL_INTERVAL'] if interval interval.to_i elsif Rails.env.development? && execution_mode.in?([:async, :async_all, :async_server]) DEFAULT_DEVELOPMENT_ASYNC_POLL_INTERVAL else DEFAULT_POLL_INTERVAL end end |
#probe_app ⇒ nil, Class
Rack compliant application to be run on the ProbeServer
358 359 360 |
# File 'lib/good_job/configuration.rb', line 358 def probe_app rails_config[:probe_app] end |
#probe_handler ⇒ nil, Symbol
Probe server handler
349 350 351 352 353 354 |
# File 'lib/good_job/configuration.rb', line 349 def probe_handler ([:probe_handler] || rails_config[:probe_handler] || env['GOOD_JOB_PROBE_HANDLER'] )&.to_sym end |
#probe_port ⇒ nil, Integer
Port of the probe server
341 342 343 344 345 |
# File 'lib/good_job/configuration.rb', line 341 def probe_port ([:probe_port] || env['GOOD_JOB_PROBE_PORT'] )&.to_i end |
#queue_select_limit ⇒ Integer
The number of queued jobs to select when polling for a job to run. This limit is intended to avoid locking a large number of rows when selecting eligible jobs from the queue. This value should be higher than the total number of threads across all good_job processes to ensure a thread can retrieve an eligible and unlocked job.
248 249 250 251 252 253 254 255 |
# File 'lib/good_job/configuration.rb', line 248 def queue_select_limit ( [:queue_select_limit] || rails_config[:queue_select_limit] || env['GOOD_JOB_QUEUE_SELECT_LIMIT'] || DEFAULT_QUEUE_SELECT_LIMIT ).to_i end |
#queue_string ⇒ String
154 155 156 157 158 159 |
# File 'lib/good_job/configuration.rb', line 154 def queue_string [:queues].presence || rails_config[:queues].presence || env['GOOD_JOB_QUEUES'].presence || '*' end |
#shutdown_timeout ⇒ Float
The number of seconds to wait for jobs to finish when shutting down before stopping the thread. -1 is forever.
200 201 202 203 204 205 206 207 |
# File 'lib/good_job/configuration.rb', line 200 def shutdown_timeout ( [:shutdown_timeout] || rails_config[:shutdown_timeout] || env['GOOD_JOB_SHUTDOWN_TIMEOUT'] || DEFAULT_SHUTDOWN_TIMEOUT ).to_f end |
#validate! ⇒ Object
104 105 106 107 |
# File 'lib/good_job/configuration.rb', line 104 def validate! self.class.validate_execution_mode(execution_mode) self.class.validate_dequeue_query_sort(dequeue_query_sort) end |