@@ -92,18 +92,20 @@ def work_off(num = 100)
9292 break if jobs . empty?
9393
9494 total += jobs . length
95- pool = Concurrent ::FixedThreadPool . new ( jobs . length )
95+ pool = Concurrent ::FixedThreadPool . new ( thread_pool_size ( jobs . length ) )
9696 jobs . each do |job |
9797 pool . post do
98+ thread_started = false
9899 self . class . lifecycle . run_callbacks ( :thread , self ) do
100+ thread_started = true
99101 success . increment if perform ( job )
100102 rescue DeserializationError => e
101103 handle_unrecoverable_error ( job , e )
102104 rescue Exception => e # rubocop:disable Lint/RescueException
103105 handle_erroring_job ( job , e )
104106 end
105107 rescue Exception => e # rubocop:disable Lint/RescueException
106- say "Job thread crashed with #{ e . class . name } : #{ e . message } " , 'error'
108+ handle_thread_error ( job , e , thread_started )
107109 end
108110 end
109111
@@ -215,6 +217,16 @@ def handle_unrecoverable_error(job, error)
215217 failed ( job )
216218 end
217219
220+ def handle_thread_error ( job , error , thread_started )
221+ phase = thread_started ? 'after perform' : 'before perform'
222+ job_say job , "thread crashed #{ phase } with #{ error . class . name } : #{ error . message } " , 'error'
223+ return if thread_started
224+
225+ handle_erroring_job ( job , error )
226+ rescue Exception => inner_error # rubocop:disable Lint/RescueException
227+ job_say job , "could not record pre-perform thread crash: #{ inner_error . class . name } : #{ inner_error . message } " , 'error'
228+ end
229+
218230 # The backend adapter may return either a list or a single job
219231 # In some backends, this can be controlled with the `max_claims` config
220232 # Either way, we map this to an array of job instances
@@ -235,6 +247,17 @@ def reload!
235247 Rails . application . reloader . reload! if defined? ( Rails . application . reloader ) && Rails . application . reloader . check!
236248 end
237249
250+ def thread_pool_size ( job_count )
251+ return job_count unless Delayed ::Job . respond_to? ( :connection_pool )
252+
253+ pool_size = Delayed ::Job . connection_pool . size
254+ return job_count unless pool_size
255+
256+ [ job_count , [ pool_size - 1 , 1 ] . max ] . min
257+ rescue StandardError
258+ job_count
259+ end
260+
238261 def clock_time
239262 Process . clock_gettime ( Process ::CLOCK_MONOTONIC )
240263 end
0 commit comments