solid_queue 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -10
  3. data/app/models/solid_queue/blocked_execution.rb +16 -10
  4. data/app/models/solid_queue/claimed_execution.rb +11 -4
  5. data/app/models/solid_queue/execution/dispatching.rb +2 -3
  6. data/app/models/solid_queue/execution.rb +32 -15
  7. data/app/models/solid_queue/failed_execution.rb +10 -6
  8. data/app/models/solid_queue/job/executable.rb +1 -1
  9. data/app/models/solid_queue/job/schedulable.rb +1 -1
  10. data/app/models/solid_queue/process/prunable.rb +6 -5
  11. data/app/models/solid_queue/process.rb +13 -6
  12. data/app/models/solid_queue/recurring_execution.rb +3 -3
  13. data/app/models/solid_queue/scheduled_execution.rb +3 -1
  14. data/app/models/solid_queue/semaphore.rb +1 -1
  15. data/lib/active_job/queue_adapters/solid_queue_adapter.rb +4 -0
  16. data/lib/generators/solid_queue/install/templates/config.yml +1 -1
  17. data/lib/puma/plugin/solid_queue.rb +1 -0
  18. data/lib/solid_queue/app_executor.rb +1 -1
  19. data/lib/solid_queue/dispatcher/recurring_task.rb +13 -7
  20. data/lib/solid_queue/dispatcher.rb +4 -4
  21. data/lib/solid_queue/engine.rb +4 -2
  22. data/lib/solid_queue/log_subscriber.rb +164 -0
  23. data/lib/solid_queue/processes/base.rb +16 -0
  24. data/lib/solid_queue/processes/interruptible.rb +1 -1
  25. data/lib/solid_queue/processes/poller.rb +7 -5
  26. data/lib/solid_queue/processes/registrable.rb +5 -23
  27. data/lib/solid_queue/processes/runnable.rb +4 -3
  28. data/lib/solid_queue/processes/signals.rb +1 -1
  29. data/lib/solid_queue/supervisor.rb +25 -24
  30. data/lib/solid_queue/version.rb +1 -1
  31. data/lib/solid_queue/worker.rb +6 -6
  32. data/lib/solid_queue.rb +19 -10
  33. metadata +23 -11
  34. data/lib/solid_queue/recurring_tasks/manager.rb +0 -31
  35. data/lib/solid_queue/recurring_tasks/schedule.rb +0 -58
  36. data/lib/solid_queue/recurring_tasks/task.rb +0 -87
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c5bed020eb4391f1885c95f2f4373e30d1eacd544e2cfcadf131c8c09079fd0
4
- data.tar.gz: 749ac036b072622cd2cc299f1fc5b1a7353a44347beccaa8407157eed8af02ef
3
+ metadata.gz: 490264bacfa32881edc69e3fa349081bfa1666785db38c7df55824ab6bd538b4
4
+ data.tar.gz: b12570f172afad018ac4709c7203276c0ba737ff90654cae02cadc3197be0357
5
5
  SHA512:
6
- metadata.gz: f39c8aadb36bc8ae5556f3cbd190e6d123ca441b14374b56c207530dd2d37d8dc4880f6e977f6bc2e047b47c886768a3c86d6fefd040a447f6d8f21e28e8a273
7
- data.tar.gz: d95c4be96c4388c6558a32f44690e9d92913e47bd01a379f09ef8b3e65a9098a2e578dd68885c36374b27e389c65d67e1100ad4d1c6908e6f675ede75bce8d3a
6
+ metadata.gz: b5909c1a726457b029d0de62bd22bf6929d84ebcddf35a56a8a0af10a0be7108ca1eb60ed48294ef77013f03d9e3c0f9b87a34d1e54ec966742abf79f5edd41f
7
+ data.tar.gz: daec7288a9652399f5dd75c0c6d8a5d5def60f9772a122a8b6212a675bb2d5e6ccee831156afd59b624204c694276f5011df64a122df7d44b578e848798cb5fe
data/README.md CHANGED
@@ -171,6 +171,7 @@ There are several settings that control how Solid Queue works that you can set a
171
171
  - `preserve_finished_jobs`: whether to keep finished jobs in the `solid_queue_jobs` table—defaults to `true`.
172
172
  - `clear_finished_jobs_after`: period to keep finished jobs around, in case `preserve_finished_jobs` is true—defaults to 1 day. **Note:** Right now, there's no automatic cleanup of finished jobs. You'd need to do this by periodically invoking `SolidQueue::Job.clear_finished_in_batches`, but this will happen automatically in the near future.
173
173
  - `default_concurrency_control_period`: the value to be used as the default for the `duration` parameter in [concurrency controls](#concurrency-controls). It defaults to 3 minutes.
174
+ - `enqueue_after_transaction_commit`: whether the job queuing is deferred to after the current Active Record transaction is committed. The default is `false`. [Read more](https://github.com/rails/rails/pull/51426).
174
175
 
175
176
 
176
177
  ## Concurrency controls
@@ -233,7 +234,7 @@ failed_execution.retry # This will re-enqueue the job as if it was enqueued for
233
234
  failed_execution.discard # This will delete the job from the system
234
235
  ```
235
236
 
236
- However, we recommend taking a look at [mission_control-jobs](https://github.com/basecamp/mission_control-jobs), a dashboard where, among other things, you can examine and retry/discard failed jobs.
237
+ However, we recommend taking a look at [mission_control-jobs](https://github.com/rails/mission_control-jobs), a dashboard where, among other things, you can examine and retry/discard failed jobs.
237
238
 
238
239
  ## Puma plugin
239
240
  We provide a Puma plugin if you want to run the Solid Queue's supervisor together with Puma and have Puma monitor and manage it. You just need to add
@@ -246,9 +247,12 @@ to your `puma.rb` configuration.
246
247
  ## Jobs and transactional integrity
247
248
  :warning: Having your jobs in the same ACID-compliant database as your application data enables a powerful yet sharp tool: taking advantage of transactional integrity to ensure some action in your app is not committed unless your job is also committed. This can be very powerful and useful, but it can also backfire if you base some of your logic on this behaviour, and in the future, you move to another active job backend, or if you simply move Solid Queue to its own database, and suddenly the behaviour changes under you.
248
249
 
250
+ By default, Solid Queue runs in the same DB as your app, and job enqueuing is _not_ deferred until any ongoing transaction is committed, which means that by default, you'll be taking advantage of this transactional integrity.
251
+
249
252
  If you prefer not to rely on this, or avoid relying on it unintentionally, you should make sure that:
250
- - Your jobs relying on specific records are always enqueued on [`after_commit` callbacks](https://guides.rubyonrails.org/active_record_callbacks.html#after-commit-and-after-rollback) or otherwise from a place where you're certain that whatever data the job will use has been committed to the database before the job is enqueued.
251
- - Or, to opt out completely from this behaviour, configure a database for Solid Queue, even if it's the same as your app, ensuring that a different connection on the thread handling requests or running jobs for your app will be used to enqueue jobs. For example:
253
+ - You set [`config.active_job.enqueue_after_transaction_commit`](https://edgeguides.rubyonrails.org/configuring.html#config-active-job-enqueue-after-transaction-commit) to `always`, if you're using Rails 7.2+.
254
+ - Or, your jobs relying on specific records are always enqueued on [`after_commit` callbacks](https://guides.rubyonrails.org/active_record_callbacks.html#after-commit-and-after-rollback) or otherwise from a place where you're certain that whatever data the job will use has been committed to the database before the job is enqueued.
255
+ - Or, you configure a database for Solid Queue, even if it's the same as your app, ensuring that a different connection on the thread handling requests or running jobs for your app will be used to enqueue jobs. For example:
252
256
 
253
257
  ```ruby
254
258
  class ApplicationRecord < ActiveRecord::Base
@@ -261,13 +265,6 @@ If you prefer not to rely on this, or avoid relying on it unintentionally, you s
261
265
  config.solid_queue.connects_to = { database: { writing: :primary, reading: :replica } }
262
266
  ```
263
267
 
264
- ## Inspiration
265
-
266
- Solid Queue has been inspired by [resque](https://github.com/resque/resque) and [GoodJob](https://github.com/bensheldon/good_job). We recommend checking out these projects as they're great examples from which we've learnt a lot.
267
-
268
- ## License
269
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
270
-
271
268
  ## Recurring tasks
272
269
  Solid Queue supports defining recurring tasks that run at specific times in the future, on a regular basis like cron jobs. These are managed by dispatcher processes and as such, they can be defined in the dispatcher's configuration like this:
273
270
  ```yml
@@ -312,3 +309,10 @@ You can still configure this in Solid Queue:
312
309
  schedule: "*/5 * * * *"
313
310
  ```
314
311
  and the job will be enqueued via `perform_later` so it'll run in Resque. However, in this case we won't track any `solid_queue_recurring_execution` record for it and there won't be any guarantees that the job is enqueued only once each time.
312
+
313
+ ## Inspiration
314
+
315
+ Solid Queue has been inspired by [resque](https://github.com/resque/resque) and [GoodJob](https://github.com/bensheldon/good_job). We recommend checking out these projects as they're great examples from which we've learnt a lot.
316
+
317
+ ## License
318
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -10,21 +10,25 @@ module SolidQueue
10
10
  scope :expired, -> { where(expires_at: ...Time.current) }
11
11
 
12
12
  class << self
13
- def unblock(count)
14
- expired.distinct.limit(count).pluck(:concurrency_key).then do |concurrency_keys|
15
- release_many releasable(concurrency_keys)
13
+ def unblock(limit)
14
+ SolidQueue.instrument(:release_many_blocked, limit: limit) do |payload|
15
+ expired.distinct.limit(limit).pluck(:concurrency_key).then do |concurrency_keys|
16
+ payload[:size] = release_many releasable(concurrency_keys)
17
+ end
16
18
  end
17
19
  end
18
20
 
19
21
  def release_many(concurrency_keys)
20
22
  # We want to release exactly one blocked execution for each concurrency key, and we need to do it
21
23
  # one by one, locking each record and acquiring the semaphore individually for each of them:
22
- Array(concurrency_keys).each { |concurrency_key| release_one(concurrency_key) }
24
+ Array(concurrency_keys).count { |concurrency_key| release_one(concurrency_key) }
23
25
  end
24
26
 
25
27
  def release_one(concurrency_key)
26
28
  transaction do
27
- ordered.where(concurrency_key: concurrency_key).limit(1).non_blocking_lock.each(&:release)
29
+ if execution = ordered.where(concurrency_key: concurrency_key).limit(1).non_blocking_lock.first
30
+ execution.release
31
+ end
28
32
  end
29
33
  end
30
34
 
@@ -38,12 +42,14 @@ module SolidQueue
38
42
  end
39
43
 
40
44
  def release
41
- transaction do
42
- if acquire_concurrency_lock
43
- promote_to_ready
44
- destroy!
45
+ SolidQueue.instrument(:release_blocked, job_id: job.id, concurrency_key: concurrency_key, released: false) do |payload|
46
+ transaction do
47
+ if acquire_concurrency_lock
48
+ promote_to_ready
49
+ destroy!
45
50
 
46
- SolidQueue.logger.debug("[SolidQueue] Unblocked job #{job.id} under #{concurrency_key}")
51
+ payload[:released] = true
52
+ end
47
53
  end
48
54
  end
49
55
  end
@@ -20,7 +20,12 @@ class SolidQueue::ClaimedExecution < SolidQueue::Execution
20
20
  end
21
21
 
22
22
  def release_all
23
- includes(:job).each(&:release)
23
+ SolidQueue.instrument(:release_many_claimed) do |payload|
24
+ includes(:job).tap do |executions|
25
+ payload[:size] = executions.size
26
+ executions.each(&:release)
27
+ end
28
+ end
24
29
  end
25
30
 
26
31
  def discard_all_in_batches(*)
@@ -45,9 +50,11 @@ class SolidQueue::ClaimedExecution < SolidQueue::Execution
45
50
  end
46
51
 
47
52
  def release
48
- transaction do
49
- job.dispatch_bypassing_concurrency_limits
50
- destroy!
53
+ SolidQueue.instrument(:release_claimed, job_id: job.id, process_id: process_id) do
54
+ transaction do
55
+ job.dispatch_bypassing_concurrency_limits
56
+ destroy!
57
+ end
51
58
  end
52
59
  end
53
60
 
@@ -9,9 +9,8 @@ module SolidQueue
9
9
  def dispatch_jobs(job_ids)
10
10
  jobs = Job.where(id: job_ids)
11
11
 
12
- Job.dispatch_all(jobs).map(&:id).tap do |dispatched_job_ids|
13
- where(job_id: dispatched_job_ids).order(:job_id).delete_all
14
- SolidQueue.logger.info("[SolidQueue] Dispatched #{dispatched_job_ids.size} jobs")
12
+ Job.dispatch_all(jobs).map(&:id).then do |dispatched_job_ids|
13
+ where(id: where(job_id: dispatched_job_ids).pluck(:id)).delete_all
15
14
  end
16
15
  end
17
16
  end
@@ -13,6 +13,10 @@ module SolidQueue
13
13
  belongs_to :job
14
14
 
15
15
  class << self
16
+ def type
17
+ model_name.element.sub("_execution", "").to_sym
18
+ end
19
+
16
20
  def create_all_from_jobs(jobs)
17
21
  insert_all execution_data_from_jobs(jobs)
18
22
  end
@@ -27,25 +31,32 @@ module SolidQueue
27
31
  pending = count
28
32
  discarded = 0
29
33
 
30
- loop do
31
- transaction do
32
- job_ids = limit(batch_size).order(:job_id).lock.pluck(:job_id)
34
+ SolidQueue.instrument(:discard_all, batch_size: batch_size, status: type, batches: 0, size: 0) do |payload|
35
+ loop do
36
+ transaction do
37
+ job_ids = limit(batch_size).order(:job_id).lock.pluck(:job_id)
38
+ discarded = discard_jobs job_ids
33
39
 
34
- discard_jobs job_ids
35
- discarded = where(job_id: job_ids).delete_all
36
- pending -= discarded
37
- end
40
+ where(job_id: job_ids).delete_all
41
+ pending -= discarded
42
+
43
+ payload[:size] += discarded
44
+ payload[:batches] += 1
45
+ end
38
46
 
39
- break if pending <= 0 || discarded == 0
47
+ break if pending <= 0 || discarded == 0
48
+ end
40
49
  end
41
50
  end
42
51
 
43
52
  def discard_all_from_jobs(jobs)
44
- transaction do
45
- job_ids = lock_all_from_jobs(jobs)
53
+ SolidQueue.instrument(:discard_all, jobs_size: jobs.size, status: type) do |payload|
54
+ transaction do
55
+ job_ids = lock_all_from_jobs(jobs)
46
56
 
47
- discard_jobs job_ids
48
- where(job_id: job_ids).delete_all
57
+ payload[:size] = discard_jobs job_ids
58
+ where(job_id: job_ids).delete_all
59
+ end
49
60
  end
50
61
  end
51
62
 
@@ -59,10 +70,16 @@ module SolidQueue
59
70
  end
60
71
  end
61
72
 
73
+ def type
74
+ self.class.type
75
+ end
76
+
62
77
  def discard
63
- with_lock do
64
- job.destroy
65
- destroy
78
+ SolidQueue.instrument(:discard, job_id: job_id, status: type) do
79
+ with_lock do
80
+ job.destroy
81
+ destroy
82
+ end
66
83
  end
67
84
  end
68
85
  end
@@ -11,15 +11,19 @@ module SolidQueue
11
11
  attr_accessor :exception
12
12
 
13
13
  def self.retry_all(jobs)
14
- transaction do
15
- dispatch_jobs lock_all_from_jobs(jobs)
14
+ SolidQueue.instrument(:retry_all, jobs_size: jobs.size) do |payload|
15
+ transaction do
16
+ payload[:size] = dispatch_jobs lock_all_from_jobs(jobs)
17
+ end
16
18
  end
17
19
  end
18
20
 
19
21
  def retry
20
- with_lock do
21
- job.prepare_for_execution
22
- destroy!
22
+ SolidQueue.instrument(:retry, job_id: job.id) do
23
+ with_lock do
24
+ job.prepare_for_execution
25
+ destroy!
26
+ end
23
27
  end
24
28
  end
25
29
 
@@ -33,5 +37,5 @@ module SolidQueue
33
37
  self.error = { exception_class: exception.class.name, message: exception.message, backtrace: exception.backtrace }
34
38
  end
35
39
  end
36
- end
40
+ end
37
41
  end
@@ -93,7 +93,7 @@ module SolidQueue
93
93
  if finished?
94
94
  :finished
95
95
  elsif execution.present?
96
- execution.model_name.element.sub("_execution", "").to_sym
96
+ execution.type
97
97
  end
98
98
  end
99
99
 
@@ -8,7 +8,7 @@ module SolidQueue
8
8
  included do
9
9
  has_one :scheduled_execution
10
10
 
11
- scope :scheduled, -> { where.not(finished_at: nil) }
11
+ scope :scheduled, -> { where(finished_at: nil) }
12
12
  end
13
13
 
14
14
  class_methods do
@@ -4,15 +4,16 @@ module SolidQueue::Process::Prunable
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- scope :prunable, -> { where("last_heartbeat_at <= ?", SolidQueue.process_alive_threshold.ago) }
7
+ scope :prunable, -> { where(last_heartbeat_at: ..SolidQueue.process_alive_threshold.ago) }
8
8
  end
9
9
 
10
10
  class_methods do
11
11
  def prune
12
- prunable.non_blocking_lock.find_in_batches(batch_size: 50) do |batch|
13
- batch.each do |process|
14
- SolidQueue.logger.info("[SolidQueue] Pruning dead process #{process.id} - #{process.metadata}")
15
- process.deregister
12
+ SolidQueue.instrument :prune_processes, size: 0 do |payload|
13
+ prunable.non_blocking_lock.find_in_batches(batch_size: 50) do |batch|
14
+ payload[:size] += batch.size
15
+
16
+ batch.each { |process| process.deregister(pruned: true) }
16
17
  end
17
18
  end
18
19
  end
@@ -12,17 +12,24 @@ class SolidQueue::Process < SolidQueue::Record
12
12
  after_destroy -> { claimed_executions.release_all }
13
13
 
14
14
  def self.register(**attributes)
15
- create!(attributes.merge(last_heartbeat_at: Time.current))
15
+ SolidQueue.instrument :register_process, **attributes do
16
+ create!(attributes.merge(last_heartbeat_at: Time.current))
17
+ end
18
+ rescue Exception => error
19
+ SolidQueue.instrument :register_process, **attributes.merge(error: error)
20
+ raise
16
21
  end
17
22
 
18
23
  def heartbeat
19
24
  touch(:last_heartbeat_at)
20
25
  end
21
26
 
22
- def deregister
23
- destroy!
24
- rescue Exception
25
- SolidQueue.logger.error("[SolidQueue] Error deregistering process #{id} - #{metadata}")
26
- raise
27
+ def deregister(pruned: false)
28
+ SolidQueue.instrument :deregister_process, process: self, pruned: pruned, claimed_size: claimed_executions.size do |payload|
29
+ destroy!
30
+ rescue Exception => error
31
+ payload[:error] = error
32
+ raise
33
+ end
27
34
  end
28
35
  end
@@ -7,12 +7,12 @@ module SolidQueue
7
7
  class << self
8
8
  def record(task_key, run_at, &block)
9
9
  transaction do
10
- if job_id = block.call
11
- create!(job_id: job_id, task_key: task_key, run_at: run_at)
10
+ block.call.tap do |active_job|
11
+ create!(job_id: active_job.provider_job_id, task_key: task_key, run_at: run_at)
12
12
  end
13
13
  end
14
14
  rescue ActiveRecord::RecordNotUnique
15
- SolidQueue.logger.info("[SolidQueue] Skipped recurring task #{task_key} at #{run_at} — already dispatched")
15
+ # Task already dispatched
16
16
  end
17
17
 
18
18
  def clear_in_batches(batch_size: 500)
@@ -16,7 +16,9 @@ module SolidQueue
16
16
  job_ids = next_batch(batch_size).non_blocking_lock.pluck(:job_id)
17
17
  if job_ids.empty? then []
18
18
  else
19
- dispatch_jobs(job_ids)
19
+ SolidQueue.instrument(:dispatch_scheduled, batch_size: batch_size) do |payload|
20
+ payload[:size] = dispatch_jobs(job_ids)
21
+ end
20
22
  end
21
23
  end
22
24
  end
@@ -70,7 +70,7 @@ module SolidQueue
70
70
  end
71
71
 
72
72
  def limit
73
- job.concurrency_limit
73
+ job.concurrency_limit || 1
74
74
  end
75
75
  end
76
76
  end
@@ -8,6 +8,10 @@ module ActiveJob
8
8
  #
9
9
  # Rails.application.config.active_job.queue_adapter = :solid_queue
10
10
  class SolidQueueAdapter
11
+ def enqueue_after_transaction_commit?
12
+ SolidQueue.enqueue_after_transaction_commit
13
+ end
14
+
11
15
  def enqueue(active_job) # :nodoc:
12
16
  SolidQueue::Job.enqueue(active_job)
13
17
  end
@@ -4,7 +4,7 @@
4
4
  # batch_size: 500
5
5
  # workers:
6
6
  # - queues: "*"
7
- # threads: 5
7
+ # threads: 3
8
8
  # processes: 1
9
9
  # polling_interval: 0.1
10
10
  #
@@ -19,6 +19,7 @@ Puma::Plugin.create do
19
19
  end
20
20
 
21
21
  launcher.events.on_stopped { stop_solid_queue }
22
+ launcher.events.on_restart { stop_solid_queue }
22
23
  end
23
24
 
24
25
  private
@@ -11,7 +11,7 @@ module SolidQueue
11
11
  end
12
12
 
13
13
  def handle_thread_error(error)
14
- SolidQueue.logger.error("[SolidQueue] #{error}")
14
+ SolidQueue.instrument(:thread_error, error: error)
15
15
 
16
16
  if SolidQueue.on_thread_error
17
17
  SolidQueue.on_thread_error.call(error)
@@ -30,10 +30,16 @@ module SolidQueue
30
30
  end
31
31
 
32
32
  def enqueue(at:)
33
- if using_solid_queue_adapter?
34
- perform_later_and_record(run_at: at)
35
- else
36
- perform_later
33
+ SolidQueue.instrument(:enqueue_recurring_task, task: key, at: at) do |payload|
34
+ if using_solid_queue_adapter?
35
+ perform_later_and_record(run_at: at)
36
+ else
37
+ payload[:other_adapter] = true
38
+
39
+ perform_later
40
+ end.tap do |active_job|
41
+ payload[:active_job_id] = active_job&.job_id
42
+ end
37
43
  end
38
44
  end
39
45
 
@@ -42,7 +48,7 @@ module SolidQueue
42
48
  end
43
49
 
44
50
  def to_s
45
- "#{class_name}.perform_later(#{arguments.map(&:inspect).join(",")}) [ #{parsed_schedule.original.to_s} ]"
51
+ "#{class_name}.perform_later(#{arguments.map(&:inspect).join(",")}) [ #{parsed_schedule.original} ]"
46
52
  end
47
53
 
48
54
  def to_h
@@ -59,7 +65,7 @@ module SolidQueue
59
65
  end
60
66
 
61
67
  def perform_later_and_record(run_at:)
62
- RecurringExecution.record(key, run_at) { perform_later.provider_job_id }
68
+ RecurringExecution.record(key, run_at) { perform_later }
63
69
  end
64
70
 
65
71
  def perform_later
@@ -82,4 +88,4 @@ module SolidQueue
82
88
  @job_class ||= class_name.safe_constantize
83
89
  end
84
90
  end
85
- end
91
+ end
@@ -19,6 +19,10 @@ module SolidQueue
19
19
  @recurring_schedule = RecurringSchedule.new(options[:recurring_tasks])
20
20
  end
21
21
 
22
+ def metadata
23
+ super.merge(batch_size: batch_size, concurrency_maintenance_interval: concurrency_maintenance&.interval, recurring_schedule: recurring_schedule.tasks.presence)
24
+ end
25
+
22
26
  private
23
27
  def poll
24
28
  batch = dispatch_next_batch
@@ -50,9 +54,5 @@ module SolidQueue
50
54
  def set_procline
51
55
  procline "waiting"
52
56
  end
53
-
54
- def metadata
55
- super.merge(batch_size: batch_size, concurrency_maintenance_interval: concurrency_maintenance&.interval, recurring_schedule: recurring_schedule.tasks.presence )
56
- end
57
57
  end
58
58
  end
@@ -18,7 +18,7 @@ module SolidQueue
18
18
 
19
19
  initializer "solid_queue.app_executor", before: :run_prepare_callbacks do |app|
20
20
  config.solid_queue.app_executor ||= app.executor
21
- config.solid_queue.on_thread_error ||= -> (exception) { Rails.error.report(exception, handled: false) }
21
+ config.solid_queue.on_thread_error ||= ->(exception) { Rails.error.report(exception, handled: false) }
22
22
 
23
23
  SolidQueue.app_executor = config.solid_queue.app_executor
24
24
  SolidQueue.on_thread_error = config.solid_queue.on_thread_error
@@ -26,8 +26,10 @@ module SolidQueue
26
26
 
27
27
  initializer "solid_queue.logger" do |app|
28
28
  ActiveSupport.on_load(:solid_queue) do
29
- self.logger = app.logger
29
+ self.logger ||= app.logger
30
30
  end
31
+
32
+ SolidQueue::LogSubscriber.attach_to :solid_queue
31
33
  end
32
34
 
33
35
  initializer "solid_queue.active_job.extensions" do