solid_queue 0.5.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 952d693063dae16e88a88acb2f8d77f396472cb29811e7ab2c47c06fc400cf10
4
- data.tar.gz: 338ad6a0057939a54997cdef138fa5e62e974112625c43fd65240354a0ba760a
3
+ metadata.gz: c2734f6cbcc795345207dc0cf221bd2744f2f98449da8b0edfc8175f3bbd7869
4
+ data.tar.gz: c4b4c2eca7dcb93e86a2f69d220ba1b9f8817c1d52a7cd1ff137ed5ec84e50f8
5
5
  SHA512:
6
- metadata.gz: b0bddd34b216770c9e0658bb620ae8801ab500074692417aeb0907c1f22f4f9e40a6233266aa69c1aa2b015dc294864d529659f0ee4adbdfdbef647d03fb4d35
7
- data.tar.gz: f2323054f8fdc5ee686f738d2a8359b23fe88f00b1b376cc18e99588bacc9df3be2e3a8bb660ce31db854f0fcca91560ad4d703a737b1d05c3a1dea7817c10a2
6
+ metadata.gz: 9d09b58e43c4bc19ad2ab89d10072b36b53a449e9602f5c5a8fc7b637e91d8472eb70f417148657e6b146e5cd1034025afdbe6d39fa2b9fc82ce6bba3997e57f
7
+ data.tar.gz: 27168fd2216fbca4e9b19677a7885b23663012d8aed7bf54c25be8335bd528a733b55790e662a30815b9ba24d824390372eff24ed0b9f72947b6ff4feeec17c5
@@ -29,8 +29,21 @@ class SolidQueue::ClaimedExecution < SolidQueue::Execution
29
29
  def release_all
30
30
  SolidQueue.instrument(:release_many_claimed) do |payload|
31
31
  includes(:job).tap do |executions|
32
- payload[:size] = executions.size
33
32
  executions.each(&:release)
33
+
34
+ payload[:size] = executions.size
35
+ end
36
+ end
37
+ end
38
+
39
+ def fail_all_with(error)
40
+ SolidQueue.instrument(:fail_many_claimed) do |payload|
41
+ includes(:job).tap do |executions|
42
+ executions.each { |execution| execution.failed_with(error) }
43
+
44
+ payload[:process_ids] = executions.map(&:process_id).uniq
45
+ payload[:job_ids] = executions.map(&:job_id).uniq
46
+ payload[:size] = executions.size
34
47
  end
35
48
  end
36
49
  end
@@ -69,6 +82,13 @@ class SolidQueue::ClaimedExecution < SolidQueue::Execution
69
82
  raise UndiscardableError, "Can't discard a job in progress"
70
83
  end
71
84
 
85
+ def failed_with(error)
86
+ transaction do
87
+ job.failed_with(error)
88
+ destroy!
89
+ end
90
+ end
91
+
72
92
  private
73
93
  def execute
74
94
  ActiveJob::Base.execute(job.arguments)
@@ -83,11 +103,4 @@ class SolidQueue::ClaimedExecution < SolidQueue::Execution
83
103
  destroy!
84
104
  end
85
105
  end
86
-
87
- def failed_with(error)
88
- transaction do
89
- job.failed_with(error)
90
- destroy!
91
- end
92
- end
93
106
  end
@@ -8,7 +8,19 @@ module SolidQueue
8
8
  included do
9
9
  has_many :claimed_executions
10
10
 
11
- after_destroy -> { claimed_executions.release_all }, if: :claims_executions?
11
+ after_destroy :release_all_claimed_executions
12
+ end
13
+
14
+ def fail_all_claimed_executions_with(error)
15
+ if claims_executions?
16
+ claimed_executions.fail_all_with(error)
17
+ end
18
+ end
19
+
20
+ def release_all_claimed_executions
21
+ if claims_executions?
22
+ claimed_executions.release_all
23
+ end
12
24
  end
13
25
 
14
26
  private
@@ -15,11 +15,18 @@ module SolidQueue
15
15
  prunable.non_blocking_lock.find_in_batches(batch_size: 50) do |batch|
16
16
  payload[:size] += batch.size
17
17
 
18
- batch.each { |process| process.deregister(pruned: true) }
18
+ batch.each(&:prune)
19
19
  end
20
20
  end
21
21
  end
22
22
  end
23
+
24
+ def prune
25
+ error = Processes::ProcessPrunedError.new(last_heartbeat_at)
26
+ fail_all_claimed_executions_with(error)
27
+
28
+ deregister(pruned: true)
29
+ end
23
30
  end
24
31
  end
25
32
  end
@@ -4,7 +4,7 @@ class SolidQueue::Process < SolidQueue::Record
4
4
  include Executor, Prunable
5
5
 
6
6
  belongs_to :supervisor, class_name: "SolidQueue::Process", optional: true, inverse_of: :supervisees
7
- has_many :supervisees, class_name: "SolidQueue::Process", inverse_of: :supervisor, foreign_key: :supervisor_id, dependent: :destroy
7
+ has_many :supervisees, class_name: "SolidQueue::Process", inverse_of: :supervisor, foreign_key: :supervisor_id
8
8
 
9
9
  store :metadata, coder: JSON
10
10
 
@@ -13,10 +13,10 @@ class SolidQueue::Process < SolidQueue::Record
13
13
  create!(attributes.merge(last_heartbeat_at: Time.current)).tap do |process|
14
14
  payload[:process_id] = process.id
15
15
  end
16
+ rescue Exception => error
17
+ payload[:error] = error
18
+ raise
16
19
  end
17
- rescue Exception => error
18
- SolidQueue.instrument :register_process, **attributes.merge(error: error)
19
- raise
20
20
  end
21
21
 
22
22
  def heartbeat
@@ -25,12 +25,19 @@ class SolidQueue::Process < SolidQueue::Record
25
25
 
26
26
  def deregister(pruned: false)
27
27
  SolidQueue.instrument :deregister_process, process: self, pruned: pruned do |payload|
28
- payload[:claimed_size] = claimed_executions.size if claims_executions?
29
-
30
28
  destroy!
29
+
30
+ unless supervised? || pruned
31
+ supervisees.each(&:deregister)
32
+ end
31
33
  rescue Exception => error
32
34
  payload[:error] = error
33
35
  raise
34
36
  end
35
37
  end
38
+
39
+ private
40
+ def supervised?
41
+ supervisor_id.present?
42
+ end
36
43
  end
@@ -25,7 +25,7 @@ module SolidQueue
25
25
  def record(task_key, run_at, &block)
26
26
  transaction do
27
27
  block.call.tap do |active_job|
28
- if active_job
28
+ if active_job && active_job.successfully_enqueued?
29
29
  create_or_insert!(job_id: active_job.provider_job_id, task_key: task_key, run_at: run_at)
30
30
  end
31
31
  end
@@ -43,7 +43,7 @@ module SolidQueue
43
43
  def enqueue(at:)
44
44
  SolidQueue.instrument(:enqueue_recurring_task, task: key, at: at) do |payload|
45
45
  active_job = if using_solid_queue_adapter?
46
- perform_later_and_record(run_at: at)
46
+ enqueue_and_record(run_at: at)
47
47
  else
48
48
  payload[:other_adapter] = true
49
49
 
@@ -87,8 +87,15 @@ module SolidQueue
87
87
  job_class.queue_adapter_name.inquiry.solid_queue?
88
88
  end
89
89
 
90
- def perform_later_and_record(run_at:)
91
- RecurringExecution.record(key, run_at) { perform_later }
90
+ def enqueue_and_record(run_at:)
91
+ RecurringExecution.record(key, run_at) do
92
+ job_class.new(*arguments_with_kwargs).tap do |active_job|
93
+ active_job.run_callbacks(:enqueue) do
94
+ Job.enqueue(active_job)
95
+ end
96
+ active_job.successfully_enqueued = true
97
+ end
98
+ end
92
99
  end
93
100
 
94
101
  def perform_later(&block)
@@ -0,0 +1,5 @@
1
+ class AddNameToProcesses < ActiveRecord::Migration[7.1]
2
+ def change
3
+ add_column :solid_queue_processes, :name, :string
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ class MakeNameNotNull < ActiveRecord::Migration[7.1]
2
+ def up
3
+ SolidQueue::Process.where(name: nil).find_each do |process|
4
+ process.name ||= [ process.kind.downcase, SecureRandom.hex(10) ].join("-")
5
+ process.save!
6
+ end
7
+
8
+ change_column :solid_queue_processes, :name, :string, null: false
9
+ add_index :solid_queue_processes, [ :name, :supervisor_id ], unique: true
10
+ end
11
+
12
+ def down
13
+ remove_index :solid_queue_processes, [ :name, :supervisor_id ]
14
+ change_column :solid_queue_processes, :name, :string, null: true
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ class ChangeSolidQueueRecurringTasksStaticToNotNull < ActiveRecord::Migration[7.1]
2
+ def change
3
+ change_column_null :solid_queue_recurring_tasks, :static, false, true
4
+ end
5
+ end
@@ -2,6 +2,12 @@
2
2
 
3
3
  module SolidQueue
4
4
  class Configuration
5
+ class Process < Struct.new(:kind, :attributes)
6
+ def instantiate
7
+ "SolidQueue::#{kind.to_s.titleize}".safe_constantize.new(**attributes)
8
+ end
9
+ end
10
+
5
11
  WORKER_DEFAULTS = {
6
12
  queues: "*",
7
13
  threads: 3,
@@ -17,33 +23,20 @@ module SolidQueue
17
23
  recurring_tasks: []
18
24
  }
19
25
 
26
+ DEFAULT_CONFIG = {
27
+ workers: [ WORKER_DEFAULTS ],
28
+ dispatchers: [ DISPATCHER_DEFAULTS ]
29
+ }
30
+
20
31
  def initialize(mode: :fork, load_from: nil)
21
32
  @mode = mode.to_s.inquiry
22
33
  @raw_config = config_from(load_from)
23
34
  end
24
35
 
25
- def processes
36
+ def configured_processes
26
37
  dispatchers + workers
27
38
  end
28
39
 
29
- def workers
30
- workers_options.flat_map do |worker_options|
31
- processes = if mode.fork?
32
- worker_options.fetch(:processes, WORKER_DEFAULTS[:processes])
33
- else
34
- WORKER_DEFAULTS[:processes]
35
- end
36
- processes.times.map { Worker.new(**worker_options.with_defaults(WORKER_DEFAULTS)) }
37
- end
38
- end
39
-
40
- def dispatchers
41
- dispatchers_options.map do |dispatcher_options|
42
- recurring_tasks = parse_recurring_tasks dispatcher_options[:recurring_tasks]
43
- Dispatcher.new **dispatcher_options.merge(recurring_tasks: recurring_tasks).with_defaults(DISPATCHER_DEFAULTS)
44
- end
45
- end
46
-
47
40
  def max_number_of_threads
48
41
  # At most "threads" in each worker + 1 thread for the worker + 1 thread for the heartbeat task
49
42
  workers_options.map { |options| options[:threads] }.max + 2
@@ -54,23 +47,46 @@ module SolidQueue
54
47
 
55
48
  DEFAULT_CONFIG_FILE_PATH = "config/solid_queue.yml"
56
49
 
50
+ def workers
51
+ workers_options.flat_map do |worker_options|
52
+ processes = if mode.fork?
53
+ worker_options.fetch(:processes, WORKER_DEFAULTS[:processes])
54
+ else
55
+ WORKER_DEFAULTS[:processes]
56
+ end
57
+ processes.times.map { Process.new(:worker, worker_options.with_defaults(WORKER_DEFAULTS)) }
58
+ end
59
+ end
60
+
61
+ def dispatchers
62
+ dispatchers_options.map do |dispatcher_options|
63
+ recurring_tasks = parse_recurring_tasks dispatcher_options[:recurring_tasks]
64
+ Process.new :dispatcher, dispatcher_options.merge(recurring_tasks: recurring_tasks).with_defaults(DISPATCHER_DEFAULTS)
65
+ end
66
+ end
67
+
57
68
  def config_from(file_or_hash, env: Rails.env)
58
- config = load_config_from(file_or_hash)
59
- config[env.to_sym] ? config[env.to_sym] : config
69
+ load_config_from(file_or_hash).then do |config|
70
+ config = config[env.to_sym] ? config[env.to_sym] : config
71
+ if (config.keys & DEFAULT_CONFIG.keys).any? then config
72
+ else
73
+ DEFAULT_CONFIG
74
+ end
75
+ end
60
76
  end
61
77
 
62
78
  def workers_options
63
- @workers_options ||= options_from_raw_config(:workers, WORKER_DEFAULTS)
79
+ @workers_options ||= options_from_raw_config(:workers)
64
80
  .map { |options| options.dup.symbolize_keys }
65
81
  end
66
82
 
67
83
  def dispatchers_options
68
- @dispatchers_options ||= options_from_raw_config(:dispatchers, DISPATCHER_DEFAULTS)
84
+ @dispatchers_options ||= options_from_raw_config(:dispatchers)
69
85
  .map { |options| options.dup.symbolize_keys }
70
86
  end
71
87
 
72
- def options_from_raw_config(key, defaults)
73
- raw_config.empty? ? [ defaults ] : Array(raw_config[key])
88
+ def options_from_raw_config(key)
89
+ Array(raw_config[key])
74
90
  end
75
91
 
76
92
  def parse_recurring_tasks(tasks)
@@ -12,11 +12,15 @@ class SolidQueue::LogSubscriber < ActiveSupport::LogSubscriber
12
12
  end
13
13
 
14
14
  def release_many_claimed(event)
15
- debug formatted_event(event, action: "Release claimed jobs", **event.payload.slice(:size))
15
+ info formatted_event(event, action: "Release claimed jobs", **event.payload.slice(:size))
16
+ end
17
+
18
+ def fail_many_claimed(event)
19
+ warn formatted_event(event, action: "Fail claimed jobs", **event.payload.slice(:job_ids, :process_ids))
16
20
  end
17
21
 
18
22
  def release_claimed(event)
19
- debug formatted_event(event, action: "Release claimed job", **event.payload.slice(:job_id, :process_id))
23
+ info formatted_event(event, action: "Release claimed job", **event.payload.slice(:job_id, :process_id))
20
24
  end
21
25
 
22
26
  def retry_all(event)
@@ -63,7 +67,8 @@ class SolidQueue::LogSubscriber < ActiveSupport::LogSubscriber
63
67
  attributes = {
64
68
  pid: process.pid,
65
69
  hostname: process.hostname,
66
- process_id: process.process_id
70
+ process_id: process.process_id,
71
+ name: process.name
67
72
  }.merge(process.metadata)
68
73
 
69
74
  info formatted_event(event, action: "Started #{process.kind}", **attributes)
@@ -75,7 +80,8 @@ class SolidQueue::LogSubscriber < ActiveSupport::LogSubscriber
75
80
  attributes = {
76
81
  pid: process.pid,
77
82
  hostname: process.hostname,
78
- process_id: process.process_id
83
+ process_id: process.process_id,
84
+ name: process.name
79
85
  }.merge(process.metadata)
80
86
 
81
87
  info formatted_event(event, action: "Shutdown #{process.kind}", **attributes)
@@ -83,7 +89,7 @@ class SolidQueue::LogSubscriber < ActiveSupport::LogSubscriber
83
89
 
84
90
  def register_process(event)
85
91
  process_kind = event.payload[:kind]
86
- attributes = event.payload.slice(:pid, :hostname, :process_id)
92
+ attributes = event.payload.slice(:pid, :hostname, :process_id, :name)
87
93
 
88
94
  if error = event.payload[:error]
89
95
  warn formatted_event(event, action: "Error registering #{process_kind}", **attributes.merge(error: formatted_error(error)))
@@ -99,6 +105,7 @@ class SolidQueue::LogSubscriber < ActiveSupport::LogSubscriber
99
105
  process_id: process.id,
100
106
  pid: process.pid,
101
107
  hostname: process.hostname,
108
+ name: process.name,
102
109
  last_heartbeat_at: process.last_heartbeat_at.iso8601,
103
110
  claimed_size: event.payload[:claimed_size],
104
111
  pruned: event.payload[:pruned]
@@ -147,7 +154,7 @@ class SolidQueue::LogSubscriber < ActiveSupport::LogSubscriber
147
154
  termsig: status.termsig
148
155
 
149
156
  if replaced_fork = event.payload[:fork]
150
- info formatted_event(event, action: "Replaced terminated #{replaced_fork.kind}", **attributes.merge(hostname: replaced_fork.hostname))
157
+ info formatted_event(event, action: "Replaced terminated #{replaced_fork.kind}", **attributes.merge(hostname: replaced_fork.hostname, name: replaced_fork.name))
151
158
  else
152
159
  warn formatted_event(event, action: "Tried to replace forked process but it had already died", **attributes)
153
160
  end
@@ -6,6 +6,12 @@ module SolidQueue
6
6
  include Callbacks # Defines callbacks needed by other concerns
7
7
  include AppExecutor, Registrable, Interruptible, Procline
8
8
 
9
+ attr_reader :name
10
+
11
+ def initialize(*)
12
+ @name = generate_name
13
+ end
14
+
9
15
  def kind
10
16
  self.class.name.demodulize
11
17
  end
@@ -21,6 +27,11 @@ module SolidQueue
21
27
  def metadata
22
28
  {}
23
29
  end
30
+
31
+ private
32
+ def generate_name
33
+ [ kind.downcase, SecureRandom.hex(10) ].join("-")
34
+ end
24
35
  end
25
36
  end
26
37
  end
@@ -8,6 +8,8 @@ module SolidQueue::Processes
8
8
 
9
9
  def initialize(polling_interval:, **options)
10
10
  @polling_interval = polling_interval
11
+
12
+ super(**options)
11
13
  end
12
14
 
13
15
  def metadata
@@ -43,10 +45,12 @@ module SolidQueue::Processes
43
45
  end
44
46
 
45
47
  def with_polling_volume
46
- if SolidQueue.silence_polling? && ActiveRecord::Base.logger
47
- ActiveRecord::Base.logger.silence { yield }
48
- else
49
- yield
48
+ SolidQueue.instrument(:polling) do
49
+ if SolidQueue.silence_polling? && ActiveRecord::Base.logger
50
+ ActiveRecord::Base.logger.silence { yield }
51
+ else
52
+ yield
53
+ end
50
54
  end
51
55
  end
52
56
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidQueue
4
+ module Processes
5
+ class ProcessExitError < RuntimeError
6
+ def initialize(status)
7
+ message = case
8
+ when status.exitstatus.present? then "Process pid=#{status.pid} exited with status #{status. exitstatus}"
9
+ when status.signaled? then "Process pid=#{status.pid} received unhandled signal #{status. termsig}"
10
+ else "Process pid=#{status.pid} exited unexpectedly"
11
+ end
12
+
13
+ super(message)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ module SolidQueue
2
+ module Processes
3
+ class ProcessMissingError < RuntimeError
4
+ def initialize
5
+ super("The process that was running this job no longer exists")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidQueue
4
+ module Processes
5
+ class ProcessPrunedError < RuntimeError
6
+ def initialize(last_heartbeat_at)
7
+ super("Process was found dead and pruned (last heartbeat at: #{last_heartbeat_at}")
8
+ end
9
+ end
10
+ end
11
+ end
@@ -21,6 +21,7 @@ module SolidQueue::Processes
21
21
  def register
22
22
  @process = SolidQueue::Process.register \
23
23
  kind: kind,
24
+ name: name,
24
25
  pid: pid,
25
26
  hostname: hostname,
26
27
  supervisor: try(:supervisor),
@@ -25,10 +25,6 @@ module SolidQueue::Processes
25
25
  @thread&.join
26
26
  end
27
27
 
28
- def name
29
- @name ||= [ kind.downcase, SecureRandom.hex(6) ].join("-")
30
- end
31
-
32
28
  def alive?
33
29
  !running_async? || @thread.alive?
34
30
  end
@@ -23,10 +23,13 @@ module SolidQueue
23
23
  attr_reader :threads
24
24
 
25
25
  def start_process(configured_process)
26
- configured_process.supervised_by process
27
- configured_process.start
26
+ process_instance = configured_process.instantiate.tap do |instance|
27
+ instance.supervised_by process
28
+ end
29
+
30
+ process_instance.start
28
31
 
29
- threads[configured_process.name] = configured_process
32
+ threads[process_instance.name] = process_instance
30
33
  end
31
34
 
32
35
  def stop_threads
@@ -6,7 +6,9 @@ module SolidQueue
6
6
 
7
7
  def initialize(*)
8
8
  super
9
+
9
10
  @forks = {}
11
+ @configured_processes = {}
10
12
  end
11
13
 
12
14
  def kind
@@ -14,7 +16,7 @@ module SolidQueue
14
16
  end
15
17
 
16
18
  private
17
- attr_reader :forks
19
+ attr_reader :forks, :configured_processes
18
20
 
19
21
  def supervise
20
22
  loop do
@@ -33,14 +35,17 @@ module SolidQueue
33
35
  end
34
36
 
35
37
  def start_process(configured_process)
36
- configured_process.supervised_by process
37
- configured_process.mode = :fork
38
+ process_instance = configured_process.instantiate.tap do |instance|
39
+ instance.supervised_by process
40
+ instance.mode = :fork
41
+ end
38
42
 
39
43
  pid = fork do
40
- configured_process.start
44
+ process_instance.start
41
45
  end
42
46
 
43
- forks[pid] = configured_process
47
+ configured_processes[pid] = configured_process
48
+ forks[pid] = process_instance
44
49
  end
45
50
 
46
51
  def terminate_gracefully
@@ -86,7 +91,11 @@ module SolidQueue
86
91
  pid, status = ::Process.waitpid2(-1, ::Process::WNOHANG)
87
92
  break unless pid
88
93
 
89
- forks.delete(pid)
94
+ if (terminated_fork = forks.delete(pid)) && !status.exited? || status.exitstatus > 0
95
+ handle_claimed_jobs_by(terminated_fork, status)
96
+ end
97
+
98
+ configured_processes.delete(pid)
90
99
  end
91
100
  rescue SystemCallError
92
101
  # All children already reaped
@@ -94,13 +103,22 @@ module SolidQueue
94
103
 
95
104
  def replace_fork(pid, status)
96
105
  SolidQueue.instrument(:replace_fork, supervisor_pid: ::Process.pid, pid: pid, status: status) do |payload|
97
- if supervised_fork = forks.delete(pid)
98
- payload[:fork] = supervised_fork
99
- start_process(supervised_fork)
106
+ if terminated_fork = forks.delete(pid)
107
+ payload[:fork] = terminated_fork
108
+ handle_claimed_jobs_by(terminated_fork, status)
109
+
110
+ start_process(configured_processes.delete(pid))
100
111
  end
101
112
  end
102
113
  end
103
114
 
115
+ def handle_claimed_jobs_by(terminated_fork, status)
116
+ if registered_process = process.supervisees.find_by(name: terminated_fork.name)
117
+ error = Processes::ProcessExitError.new(status)
118
+ registered_process.fail_all_claimed_executions_with(error)
119
+ end
120
+ end
121
+
104
122
  def all_forks_terminated?
105
123
  forks.empty?
106
124
  end
@@ -3,7 +3,7 @@ module SolidQueue
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- after_boot :release_orphaned_executions
6
+ after_boot :fail_orphaned_executions
7
7
  end
8
8
 
9
9
  private
@@ -27,8 +27,10 @@ module SolidQueue
27
27
  wrap_in_app_executor { SolidQueue::Process.prune }
28
28
  end
29
29
 
30
- def release_orphaned_executions
31
- wrap_in_app_executor { SolidQueue::ClaimedExecution.orphaned.release_all }
30
+ def fail_orphaned_executions
31
+ wrap_in_app_executor do
32
+ ClaimedExecution.orphaned.fail_all_with(Processes::ProcessMissingError.new)
33
+ end
32
34
  end
33
35
  end
34
36
  end
@@ -9,13 +9,18 @@ module SolidQueue
9
9
  SolidQueue.supervisor = true
10
10
  configuration = Configuration.new(mode: mode, load_from: load_configuration_from)
11
11
 
12
- klass = mode == :fork ? ForkSupervisor : AsyncSupervisor
13
- klass.new(configuration).tap(&:start)
12
+ if configuration.configured_processes.any?
13
+ klass = mode == :fork ? ForkSupervisor : AsyncSupervisor
14
+ klass.new(configuration).tap(&:start)
15
+ else
16
+ abort "No workers or processed configured. Exiting..."
17
+ end
14
18
  end
15
19
  end
16
20
 
17
21
  def initialize(configuration)
18
22
  @configuration = configuration
23
+ super
19
24
  end
20
25
 
21
26
  def start
@@ -44,7 +49,7 @@ module SolidQueue
44
49
  end
45
50
 
46
51
  def start_processes
47
- configuration.processes.each { |configured_process| start_process(configured_process) }
52
+ configuration.configured_processes.each { |configured_process| start_process(configured_process) }
48
53
  end
49
54
 
50
55
  def stopped?
@@ -1,3 +1,3 @@
1
1
  module SolidQueue
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rosa Gutierrez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-14 00:00:00.000000000 Z
11
+ date: 2024-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -220,6 +220,9 @@ files:
220
220
  - db/migrate/20240110143450_add_missing_index_to_blocked_executions.rb
221
221
  - db/migrate/20240218110712_create_recurring_executions.rb
222
222
  - db/migrate/20240719134516_create_recurring_tasks.rb
223
+ - db/migrate/20240811173327_add_name_to_processes.rb
224
+ - db/migrate/20240813160053_make_name_not_null.rb
225
+ - db/migrate/20240819165045_change_solid_queue_recurring_tasks_static_to_not_null.rb
223
226
  - lib/active_job/concurrency_controls.rb
224
227
  - lib/active_job/queue_adapters/solid_queue_adapter.rb
225
228
  - lib/generators/solid_queue/install/USAGE
@@ -239,6 +242,9 @@ files:
239
242
  - lib/solid_queue/processes/callbacks.rb
240
243
  - lib/solid_queue/processes/interruptible.rb
241
244
  - lib/solid_queue/processes/poller.rb
245
+ - lib/solid_queue/processes/process_exit_error.rb
246
+ - lib/solid_queue/processes/process_missing_error.rb
247
+ - lib/solid_queue/processes/process_pruned_error.rb
242
248
  - lib/solid_queue/processes/procline.rb
243
249
  - lib/solid_queue/processes/registrable.rb
244
250
  - lib/solid_queue/processes/runnable.rb