Skip to content

Commit

Permalink
tmp: work around issues in Rails 7.1
Browse files Browse the repository at this point in the history
  • Loading branch information
bquorning committed Oct 11, 2023
1 parent a655b7b commit 74bd98d
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 14 deletions.
18 changes: 16 additions & 2 deletions lib/active_record_host_pool/clear_query_cache_patch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,20 @@
# This is a private Rails API and may change in future releases as they're
# actively working on sharding in Rails 6 and above.
module ActiveRecordHostPool
# For Rails 7.1.
module NewClearQueryCachePatch
def clear_query_caches_for_current_thread
ActiveRecord::Base.connection_handler.all_connection_pools.each do |pool|
pool._unproxied_connection.clear_query_cache if pool.active_connection?
end
end
end

# For Rails 6.1 & 7.0.
module ClearOnHandlerPatch
def clear_on_handler(handler)
# def clear_on_handler(handler) # reinstate when 7.1 works
# Work around https://github.com/rails/rails/commit/4a41b758208e3ea817cc9b756d35cb6c53a884db
def clear_on_handler(handler, _owner = nil)
handler.all_connection_pools.each do |pool|
pool._unproxied_connection.clear_query_cache if pool.active_connection?
end
Expand All @@ -39,7 +50,10 @@ def clear_query_caches_for_current_thread
end

case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
when '6.1', '7.0', '7.1'
when '7.1'
# Fix https://github.com/rails/rails/commit/401e2f24161ed6047ae33c322aaf6584b7728ab9
ActiveRecord::Base.singleton_class.prepend(ActiveRecordHostPool::NewClearQueryCachePatch)
when '6.1', '7.0'
ActiveRecord::Base.singleton_class.prepend(ActiveRecordHostPool::ClearOnHandlerPatch)
when '6.0'
ActiveRecord::Base.singleton_class.prepend(ActiveRecordHostPool::ClearQueryCachePatch)
Expand Down
29 changes: 23 additions & 6 deletions lib/active_record_host_pool/connection_adapter_mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,16 @@ def self.included(base)
base.class_eval do
attr_reader(:_host_pool_current_database)

alias_method :execute_without_switching, :execute
alias_method :execute, :execute_with_switching
# raw_execute instead of execute after
# https://github.com/rails/rails/commit/f69bbcbc0752ca5d5af327d55922614a26f5c7e9
case "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"
when '7.1'
alias_method :raw_execute_without_switching, :raw_execute
alias_method :raw_execute, :raw_execute_with_switching
else
alias_method :execute_without_switching, :execute
alias_method :execute, :execute_with_switching
end

alias_method :drop_database_without_no_switching, :drop_database
alias_method :drop_database, :drop_database_with_no_switching
Expand All @@ -50,11 +58,20 @@ def self.ruby2_keywords(*); end unless respond_to?(:ruby2_keywords, true)
# This one really does need ruby2_keywords; in Rails 6.0 the method does not take
# any keyword arguments, but in Rails 7.0 it does. So, we don't know whether or not
# what we're delegating to takes kwargs, so ruby2_keywords is needed.
ruby2_keywords def execute_with_switching(*args)
if _host_pool_current_database && !_no_switch
_switch_connection
if ActiveRecord.version >= Gem::Version.new('7.1')
ruby2_keywords def raw_execute_with_switching(*args)
if _host_pool_current_database && !_no_switch
_switch_connection
end
raw_execute_without_switching(*args)
end
else
ruby2_keywords def execute_with_switching(*args)
if _host_pool_current_database && !_no_switch
_switch_connection
end
execute_without_switching(*args)
end
execute_without_switching(*args)
end

def drop_database_with_no_switching(*args)
Expand Down
3 changes: 2 additions & 1 deletion lib/active_record_host_pool/pool_proxy_6_1.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ def _connection_proxy_for(connection, database)

@connection_proxy_cache[key] ||= begin
cx = ActiveRecordHostPool::ConnectionProxy.new(connection, database)
cx.execute('select 1')
# Work around https://github.com/rails/rails/pull/48061/commits/63c0d6b31bcd0fc33745ec6fd278b2d1aab9be54
# cx.raw_execute('SELECT 1')
cx
end
end
Expand Down
6 changes: 4 additions & 2 deletions test/test_arhp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ def test_checkout

def test_no_switch_when_creating_db
conn = Pool1DbA.connection
assert_called(conn, :execute_without_switching) do
meth = ActiveRecord.version >= Gem::Version.new('7.1') ? :raw_execute_without_switching : :execute_without_switching
assert_called(conn, meth) do
refute_called(conn, :_switch_connection) do
assert conn._host_pool_current_database
conn.create_database(:some_args)
Expand All @@ -132,7 +133,8 @@ def test_no_switch_when_creating_db

def test_no_switch_when_dropping_db
conn = Pool1DbA.connection
assert_called(conn, :execute_without_switching) do
meth = ActiveRecord.version >= Gem::Version.new('7.1') ? :raw_execute_without_switching : :execute_without_switching
assert_called(conn, meth) do
refute_called(conn, :_switch_connection) do
assert conn._host_pool_current_database
conn.drop_database(:some_args)
Expand Down
18 changes: 15 additions & 3 deletions test/test_thread_safety.rb
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,29 @@ def test_each_thread_has_its_own_connection_and_can_switch
end

def assert_query_host_1_db_a(sleep_time: 0)
result = Pool1DbA.connection.execute("SELECT val, SLEEP(#{sleep_time}) from tests")
if ActiveRecord.version >= Gem::Version.new('7.1')
result = Pool1DbA.connection.raw_execute("SELECT val, SLEEP(#{sleep_time}) from tests", nil)
else
result = Pool1DbA.connection.execute("SELECT val, SLEEP(#{sleep_time}) from tests")
end
assert_equal('test_Pool1DbA_value', result.first.first)
end

def assert_query_host_1_db_b(sleep_time: 0)
result = Pool1DbB.connection.execute("SELECT val, SLEEP(#{sleep_time}) from tests")
if ActiveRecord.version >= Gem::Version.new('7.1')
result = Pool1DbB.connection.raw_execute("SELECT val, SLEEP(#{sleep_time}) from tests", nil)
else
result = Pool1DbB.connection.execute("SELECT val, SLEEP(#{sleep_time}) from tests")
end
assert_equal('test_Pool1DbB_value', result.first.first)
end

def assert_query_host_2_db_d(sleep_time: 0)
result = Pool2DbD.connection.execute("SELECT val, SLEEP(#{sleep_time}) from tests")
if ActiveRecord.version >= Gem::Version.new('7.1')
result = Pool2DbD.connection.raw_execute("SELECT val, SLEEP(#{sleep_time}) from tests", nil)
else
result = Pool2DbD.connection.execute("SELECT val, SLEEP(#{sleep_time}) from tests")
end
assert_equal('test_Pool2DbD_value', result.first.first)
end

Expand Down

0 comments on commit 74bd98d

Please sign in to comment.