Skip to content

Commit 338c1e8

Browse files
committed
Prevent supervisor from pruning itself
For example, when coming back from being suspended and having its heartbeat expired.
1 parent d768187 commit 338c1e8

File tree

3 files changed

+25
-3
lines changed

3 files changed

+25
-3
lines changed

app/models/solid_queue/process/prunable.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ module Prunable
1010
end
1111

1212
class_methods do
13-
def prune
13+
def prune(excluding: nil)
1414
SolidQueue.instrument :prune_processes, size: 0 do |payload|
15-
prunable.non_blocking_lock.find_in_batches(batch_size: 50) do |batch|
15+
prunable.excluding(excluding).non_blocking_lock.find_in_batches(batch_size: 50) do |batch|
1616
payload[:size] += batch.size
1717

1818
batch.each(&:prune)

lib/solid_queue/supervisor/maintenance.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def stop_maintenance_task
2424
end
2525

2626
def prune_dead_processes
27-
wrap_in_app_executor { SolidQueue::Process.prune }
27+
wrap_in_app_executor { SolidQueue::Process.prune(excluding: process) }
2828
end
2929

3030
def fail_orphaned_executions

test/unit/supervisor_test.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,28 @@ class SupervisorTest < ActiveSupport::TestCase
121121
end
122122
end
123123

124+
test "prune processes with expired heartbeats" do
125+
pruned = SolidQueue::Process.register(kind: "Worker", pid: 42, name: "worker-42")
126+
127+
# Simulate expired heartbeats
128+
SolidQueue::Process.update_all(last_heartbeat_at: 10.minutes.ago)
129+
130+
not_pruned = SolidQueue::Process.register(kind: "Worker", pid: 44, name: "worker-44")
131+
132+
assert_equal 2, SolidQueue::Process.count
133+
134+
pid = run_supervisor_as_fork(load_configuration_from: { workers: [ { queues: :background } ] })
135+
wait_for_registered_processes(4)
136+
137+
terminate_process(pid)
138+
139+
skip_active_record_query_cache do
140+
assert_equal 1, SolidQueue::Process.count
141+
assert_nil SolidQueue::Process.find_by(id: pruned.id)
142+
assert SolidQueue::Process.find_by(id: not_pruned.id).present?
143+
end
144+
end
145+
124146
private
125147
def assert_registered_workers(supervisor_pid: nil, count: 1)
126148
assert_registered_processes(kind: "Worker", count: count, supervisor_pid: supervisor_pid)

0 commit comments

Comments
 (0)