Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sure to close DB connections before fork #511

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/models/solid_queue/record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ class Record < ActiveRecord::Base

connects_to(**SolidQueue.connects_to) if SolidQueue.connects_to

def self.clear_all_connections!
self.connection_handler.clear_all_connections!(:writing)
self.connection_handler.clear_all_connections!(:reading)
Comment on lines +10 to +11
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious why two calls are being made for reading and writing roles here.

By default, if no arguments are passed to ConnectionHandler#clear_all_connections! it should clear all roles. Did you see something unexpected that led you to code it this way?

Copy link
Author

@alxckn alxckn Feb 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, to be honest I was just copy pasting from another app without digging the reason.
The behavior for this method changes in rails 7.2 according to this PR. I just checked and solid queue still supports rails 7.1, so that would ensure compatibility.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alxckn Ah! That's a very good reason to do it that way. Thanks for the explanation! 👍

end

def self.non_blocking_lock
if SolidQueue.use_skip_locked
lock(Arel.sql("FOR UPDATE SKIP LOCKED"))
Expand Down
2 changes: 2 additions & 0 deletions lib/solid_queue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
module SolidQueue
extend self

ForkSafety # add fork safety hooks

DEFAULT_LOGGER = ActiveSupport::Logger.new($stdout)

mattr_accessor :logger, default: DEFAULT_LOGGER
Expand Down
15 changes: 15 additions & 0 deletions lib/solid_queue/fork_safety.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module SolidQueue
module ForkSafety
def _fork
Record.clear_all_connections!

pid = super

pid
end
end
end

Process.singleton_class.prepend(SolidQueue::ForkSafety)
2 changes: 1 addition & 1 deletion test/integration/processes_lifecycle_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class ProcessesLifecycleTest < ActiveSupport::TestCase

signal_process(@pid, :TERM, wait: 0.5)

sleep(SolidQueue.shutdown_timeout + 0.5.second)
sleep(SolidQueue.shutdown_timeout + 0.1.second)

assert_completed_job_results("no pause")
assert_job_status(no_pause, :finished)
Expand Down
Loading