class GoodJob::Adapter
Public Class Methods
@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
.
- +:inline+ executes jobs immediately in whatever process queued them (usually the web server process). This should only be used in test and development environments. - +: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. - +:async+ (or +:async_server+) executes jobs in separate threads within the Rails web server process (`bundle exec rails server`). It can be more economical for small workloads because you don't need a separate machine or environment for running your jobs, but if your web server is under heavy load or your jobs require a lot of resources, you should choose +:external+ instead. When not in the Rails web server, jobs will execute in +:external+ mode to ensure jobs are not executed within `rails console`, `rails db:migrate`, `rails assets:prepare`, etc. - +:async_all+ executes jobs in any Rails process. The default value depends on the Rails environment: - +development+ and +test+: +:inline+ - +production+ and all other environments: +:external+
@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
. @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 +“*”+. @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
.
# File lib/good_job/adapter.rb 23 def initialize(execution_mode: nil, queues: nil, max_threads: nil, poll_interval: nil) 24 @configuration = GoodJob::Configuration.new( 25 { 26 execution_mode: execution_mode, 27 queues: queues, 28 max_threads: max_threads, 29 poll_interval: poll_interval, 30 } 31 ) 32 @configuration.validate! 33 34 if execute_async? # rubocop:disable Style/GuardClause 35 @notifier = GoodJob::Notifier.new 36 @poller = GoodJob::Poller.new(poll_interval: @configuration.poll_interval) 37 @scheduler = GoodJob::Scheduler.from_configuration(@configuration, warm_cache_on_initialize: Rails.application.initialized?) 38 @notifier.recipients << [@scheduler, :create_thread] 39 @poller.recipients << [@scheduler, :create_thread] 40 41 @cron_manager = GoodJob::CronManager.new(@configuration.cron, start_on_initialize: Rails.application.initialized?) if @configuration.enable_cron? 42 end 43 end
Public Instance Methods
Enqueues the ActiveJob
job to be performed. For use by Rails; you should generally not call this directly. @param active_job [ActiveJob::Base] the job to be enqueued from #perform_later
@return [GoodJob::Job]
# File lib/good_job/adapter.rb 49 def enqueue(active_job) 50 enqueue_at(active_job, nil) 51 end
Enqueues an ActiveJob
job to be run at a specific time. For use by Rails; you should generally not call this directly. @param active_job [ActiveJob::Base] the job to be enqueued from #perform_later
@param timestamp [Integer, nil] the epoch time to perform the job @return [GoodJob::Job]
# File lib/good_job/adapter.rb 58 def enqueue_at(active_job, timestamp) 59 good_job = GoodJob::Job.enqueue( 60 active_job, 61 scheduled_at: timestamp ? Time.zone.at(timestamp) : nil, 62 create_with_advisory_lock: execute_inline? 63 ) 64 65 if execute_inline? 66 begin 67 good_job.perform 68 ensure 69 good_job.advisory_unlock 70 end 71 else 72 job_state = { queue_name: good_job.queue_name } 73 job_state[:scheduled_at] = good_job.scheduled_at if good_job.scheduled_at 74 75 executed_locally = execute_async? && @scheduler.create_thread(job_state) 76 Notifier.notify(job_state) unless executed_locally 77 end 78 79 good_job 80 end
Whether in :async
execution mode. @return [Boolean]
# File lib/good_job/adapter.rb 102 def execute_async? 103 @configuration.execution_mode == :async_all || 104 @configuration.execution_mode.in?([:async, :async_server]) && in_server_process? 105 end
Whether in :external
execution mode. @return [Boolean]
# File lib/good_job/adapter.rb 109 def execute_externally? 110 @configuration.execution_mode == :external || 111 @configuration.execution_mode.in?([:async, :async_server]) && !in_server_process? 112 end
Whether in :inline
execution mode. @return [Boolean]
# File lib/good_job/adapter.rb 116 def execute_inline? 117 @configuration.execution_mode == :inline 118 end
Shut down the thread pool executors. @param timeout [nil, Numeric, Symbol] Seconds to wait for active threads.
* +nil+, the scheduler will trigger a shutdown but not wait for it to complete. * +-1+, the scheduler will wait until the shutdown is complete. * +0+, the scheduler will immediately shutdown and stop any threads. * A positive number will wait that many seconds before stopping any remaining active threads.
@return [void]
# File lib/good_job/adapter.rb 89 def shutdown(timeout: :default) 90 timeout = if timeout == :default 91 @configuration.shutdown_timeout 92 else 93 timeout 94 end 95 96 executables = [@notifier, @poller, @scheduler].compact 97 GoodJob._shutdown_all(executables, timeout: timeout) 98 end
Private Instance Methods
Whether running in a web server process. @return [Boolean, nil]
# File lib/good_job/adapter.rb 124 def in_server_process? 125 return @_in_server_process if defined? @_in_server_process 126 127 @_in_server_process = Rails.const_defined?('Server') || 128 caller.grep(%r{config.ru}).any? || # EXAMPLE: config.ru:3:in `block in <main>' OR config.ru:3:in `new_from_string' 129 caller.grep(%{/rack/handler/}).any? || # EXAMPLE: iodine-0.7.44/lib/rack/handler/iodine.rb:13:in `start' 130 (Concurrent.on_jruby? && caller.grep(%r{jruby/rack/rails_booter}).any?) # EXAMPLE: uri:classloader:/jruby/rack/rails_booter.rb:83:in `load_environment' 131 end